سؤال

ما هي الطريقة الأكثر كفاءة / الأنيقة لتفريغ stringbuilder إلى ملف نصي؟

يمكنك ان تفعل:

outputStream.write(stringBuilder.toString().getBytes());

ولكن هل هذا فعال لملف طويل جدا؟

هل هناك طريقة أفضل؟

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

المحلول

كما أشار من قبل الآخرين، استخدم كاتبة واستخدام كاتب مخزن مؤقت، ولكن بعد ذلك لا تتصل writer.write(stringBuilder.toString()); بدلا من ذلك فقط writer.append(stringBuilder);.

تحرير: ولكن، أرى أنك قبلت إجابة مختلفة لأنها كانت بطانة واحدة. لكن هذا الحل لديه مشكلتين:

  1. لا يقبل java.nio.Charset. وبعد سيئ. يجب عليك دائما تحديد تجارب بشكل صريح.

  2. لا يزال يجعلك تعاني stringBuilder.toString(). وبعد إذا كانت البساطة هي حقا ما أنت بعد، فجرب ما يلي من جوجا مشروع:

files.write (StringBuilder، ملف، charsets.utf_8)

نصائح أخرى

يجب عليك استخدام كتاب مخزن مؤقت لتحسين الكتابة (دائما كتابة بيانات الأحرف باستخدام كاتب بدلا من الإخراج). إذا لم تكن قد تكتب بيانات الأحرف، فسوف تستخدم مؤشرات BufferedOutStream.

File file = new File("path/to/file.txt");
BufferedWriter writer = null;
try {
    writer = new BufferedWriter(new FileWriter(file));
    writer.write(stringBuilder.toString());
} finally {
    if (writer != null) writer.close();
}

أو باستخدام TRY-with-Resources (Java 7 وما فوق)

File file = new File("path/to/file.txt");
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
    writer.write(stringBuilder.toString());
}

نظرا لأنك تكتب في النهاية إلى ملف، فسيكون نهج أفضل هو الكتابة إلى الكاتب المخزن المؤقت في كثير من الأحيان بدلا من إنشاء StringBuilder ضخمة في الذاكرة وكتابة كل شيء في النهاية (اعتمادا على حالة استخدامك، فقد تكون قادرا للقضاء على stringbuilder تماما). ستحفظ الكتابة بشكل تدريجي أثناء المعالجة الذاكرة وستحقق بشكل أفضل من عرض النطاق الترددي من I / O محدود، ما لم يحاول مؤشر ترابط آخر قراءة الكثير من البيانات من القرص في نفس الوقت الذي تكتبه.

حسنا، إذا كانت السلسلة ضخمة، toString().getBytes() سيخلق البايتات المكررة (2 أو 3 مرات). حجم السلسلة.

لتجنب ذلك، يمكنك استخراج قطعة من السلسلة واكتبها في أجزاء منفصلة.

إليك كيف تبدو:

final StringBuilder aSB = ...;
final int    aLength = aSB.length();
final int    aChunk  = 1024;
final char[] aChars  = new char[aChunk];

for(int aPosStart = 0; aPosStart < aLength; aPosStart += aChunk) {
    final int aPosEnd = Math.min(aPosStart + aChunk, aLength);
    aSB.getChars(aPosStart, aPosEnd, aChars, 0);                 // إنشاء أي مخزن مؤقت جديد
    final CharArrayReader aCARead = new CharArrayReader(aChars); // إنشاء أي مخزن مؤقت جديد

    // قد يكون هذا بطيئا ولكنه لن يخلق أي أكثر مخزنة (بايت)
    int aByte;
    while((aByte = aCARead.read()) != -1)
        outputStream.write(aByte);
}

أتمنى أن يساعدك هذا.

يمكنك استخدام اباتشي المشاع IO. مكتبة، التي تمنحك fileutils.:

FileUtils.writeStringToFile(file, stringBuilder.toString(), Charset.forName("UTF-8"))

لبيانات الشخصية استخدام أفضل Reader/Writer. وبعد في حالتك، استخدم BufferedWriter. وبعد إذا كان ذلك ممكنا، استخدم BufferedWriter من البداية بدلا من StringBuilder لحفظ الذاكرة.

لاحظ أن طريقك في استدعاء غير ARG getBytes() ستستخدم الطريقة ترميز الأحرف الافتراضية للنظام الأساسي لفك تشفير الأحرف. قد يفشل هذا إذا كان ترميز النظام الأساسي الافتراضي هو مثال ISO-8859-1 بينما تحتوي بيانات السلسلة على أحرف خارج ISO-8859-1 تجديد. أفضل استخدام getBytes(charset) حيث يمكنك تحديد الإحسام بنفسك، مثل UTF-8.

إذا كانت السلسلة نفسها طويلة، فيمكنك بالتأكيد تجنب Tostring ()، مما يجعل نسخة أخرى من السلسلة. يجب أن تكون الطريقة الأكثر كفاءة للكتابة إلى الدفق شيء مثل هذا،

OutputStreamWriter writer = new OutputStreamWriter(
        new BufferedOutputStream(outputStream), "utf-8");

for (int i = 0; i < sb.length(); i++) {
    writer.write(sb.charAt(i));
}

منذ جافا 8 تحتاج فقط إلى القيام بذلك:

Files.write(Paths.get("/path/to/file/file_name.extension"), stringBuilder.toString().getBytes());

لا تحتاج إلى أي مكتبات طرف ثالث للقيام بذلك.

مرتكز على https://stackoverflow.com/a/1677317/980442.

أنا خلق هذه الوظيفة التي تستخدم OutputStreamWriter و ال write(), هذه هي الذاكرة الأمثل أيضا، أفضل من مجرد استخدام StringBuilder.toString().

public static void stringBuilderToOutputStream(
        StringBuilder sb, OutputStream out, String charsetName, int buffer)
        throws IOException {
    char[] chars = new char[buffer];
    try (OutputStreamWriter writer = new OutputStreamWriter(out, charsetName)) {
        for (int aPosStart = 0; aPosStart < sb.length(); aPosStart += buffer) {
            buffer = Math.min(buffer, sb.length() - aPosStart);
            sb.getChars(aPosStart, aPosStart + buffer, chars, 0);
            writer.write(chars, 0, buffer);
        }
    }
}

معايير لمعظم الإجابات هنا + تحسين التنفيذ: https://www.genuitec.com/dump-a-stringbuilder-to-file/

التنفيذ النهائي هو على غرار

try {
    BufferedWriter bw = new BufferedWriter(
            new OutputStreamWriter(
                    new FileOutputStream(file, append), charset), BUFFER_SIZE);
    try {
        final int length = sb.length();
        final char[] chars = new char[BUFFER_SIZE];
        int idxEnd;
        for ( int idxStart=0; idxStart<length; idxStart=idxEnd ) {
            idxEnd = Math.min(idxStart + BUFFER_SIZE, length);
            sb.getChars(idxStart, idxEnd, chars, 0);
            bw.write(chars, 0, idxEnd - idxStart);
        }
        bw.flush();
    } finally {
        bw.close();
    }
} catch ( IOException ex ) {
    ex.printStackTrace();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top