سؤال

بعد كتابة بعض المحتوى المعالج إلى دفق الإخراج ، أحتاج إلى إعادة النظر في بداية الدفق وكتابة بعض بيانات تعريف المحتوى. البيانات التي أكتبها كبيرة جدًا ، تصل إلى 4 جيجابايت ، وقد تتم كتابتها إما مباشرة إلى ملف أو إلى المخزن المؤقت في الذاكرة ، اعتمادًا على عوامل بيئية مختلفة.

كيف يمكنني تنفيذ outputstream يتيح لي كتابة رؤوس بعد الانتهاء من كتابة المحتوى؟

هل كانت مفيدة؟

المحلول

إليك دفق إخراج ملف وصول عشوائي.

لاحظ أنه إذا كان استخدامه للحصول على كمية كبيرة من الإخراج المتدفق ، يمكنك لفه مؤقتًا في bufferedoutputstream لتجنب الكثير من الكتابة الصغيرة (فقط تأكد من مسحه قبل التخلص من الغلاف أو استخدام الدفق الأساسي مباشرة).

import java.io.*;

/**
 * A positionable file output stream.
 * <p>
 * Threading Design : [x] Single Threaded  [ ] Threadsafe  [ ] Immutable  [ ] Isolated
 */

public class RandomFileOutputStream
extends OutputStream
{

// *****************************************************************************
// INSTANCE PROPERTIES
// *****************************************************************************

protected RandomAccessFile              randomFile;                             // the random file to write to
protected boolean                       sync;                                   // whether to synchronize every write

// *****************************************************************************
// INSTANCE CONSTRUCTION/INITIALIZATON/FINALIZATION, OPEN/CLOSE
// *****************************************************************************

public RandomFileOutputStream(String fnm) throws IOException {
    this(fnm,false);
    }

public RandomFileOutputStream(String fnm, boolean syn) throws IOException {
    this(new File(fnm),syn);
    }

public RandomFileOutputStream(File fil) throws IOException {
    this(fil,false);
    }

public RandomFileOutputStream(File fil, boolean syn) throws IOException {
    super();

    File                                par;                                    // parent file

    fil=fil.getAbsoluteFile();
    if((par=fil.getParentFile())!=null) { IoUtil.createDir(par); }
    randomFile=new RandomAccessFile(fil,"rw");
    sync=syn;
    }

// *****************************************************************************
// INSTANCE METHODS - OUTPUT STREAM IMPLEMENTATION
// *****************************************************************************

public void write(int val) throws IOException {
    randomFile.write(val);
    if(sync) { randomFile.getFD().sync(); }
    }

public void write(byte[] val) throws IOException {
    randomFile.write(val);
    if(sync) { randomFile.getFD().sync(); }
    }

public void write(byte[] val, int off, int len) throws IOException {
    randomFile.write(val,off,len);
    if(sync) { randomFile.getFD().sync(); }
    }

public void flush() throws IOException {
    if(sync) { randomFile.getFD().sync(); }
    }

public void close() throws IOException {
    randomFile.close();
    }

// *****************************************************************************
// INSTANCE METHODS - RANDOM ACCESS EXTENSIONS
// *****************************************************************************

public long getFilePointer() throws IOException {
    return randomFile.getFilePointer();
    }

public void setFilePointer(long pos) throws IOException {
    randomFile.seek(pos);
    }

public long getFileSize() throws IOException {
    return randomFile.length();
    }

public void setFileSize(long len) throws IOException {
    randomFile.setLength(len);
    }

public FileDescriptor getFD() throws IOException {
    return randomFile.getFD();
    }

} // END PUBLIC CLASS

نصائح أخرى

إذا كنت تعرف حجم الرأس ، فيمكنك كتابة رأس فارغ في البداية ، ثم العودة لإصلاحه RandomAccessFile في نهايةالمطاف. إذا كنت لا تعرف حجم الرأس ، فلديك أساسي لا تسمح لك أنظمة الملفات عمومًا بإدراج البيانات. لذلك تحتاج إلى الكتابة إلى ملف مؤقت ثم كتابة الملف الحقيقي.

يبدو أن لورين لديه تنفيذ ؛ و API تبدو بخير.

getFilePointer()
void seek(long pos)  

http://lucene.apache.org/java/1_4_3/api/org/apache/lucene/store/outputstream.html

أعتقد أنهم يلفون أ RandomAccessFile

تتمثل إحدى الطرق في كتابة المحتويات الأولية إلى المخزن المؤقت للذاكرة أولاً ، ثم الرؤوس إلى دفق الإخراج "الحقيقي" ، يليه تدفق المحتويات المخزنة ، ومن ثم اكتب فقط إلى الدفق غير المقلوب. يبدو أن الجزء الأولي لن يكون طويلًا ، لجعل التخزين المؤقت معقولًا. فيما يتعلق بتنفيذها ، يمكنك استخدام ByteArrayoutputStream للتخزين المؤقت ، ثم اجعل فئة OutputStream الخاصة بك تأخذ دفق الإخراج "الحقيقي" كوسيطة ؛ وتبديل فقط بين الاثنين حسب الضرورة. قد تحتاج إلى تمديد API OutputStream للسماح بتحديد ما هو البيانات الوصفية للكتابة ، لأن هذا يؤدي إلى تحول من الوضع المخزن المؤقت.

كما ذكر الإجابة الأخرى ، فإن RandomAccessFile ستعمل أيضًا ، على الرغم من عدم تنفيذ OutputStream.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top