2016-08-23 287 views
2

我需要將文件大小限制爲1 GB,而最好使用BufferedWriter使用java編寫文件時限制文件大小

是否有可能使用BufferedWriter或者我必須使用其他庫?

try (BufferedWriter writer = Files.newBufferedWriter(path)) { 
    //... 
    writer.write(lines.stream()); 
} 
+0

檢查:http://stackoverflow.com/questions/17746114/limiting-file-size-creation-with-java – Azodious

+0

* ..限制文件大小爲1 GB *所以,你想寫內容高達1GB?或者只有在內容小於1 GB時纔想寫內容? –

+1

想要停止寫入,一旦它達到1 GB .. @TAsk – hacker

回答

5

你總是可以編寫自己的OutputStream限制的書面字節數。

以下假定您想要在超過尺寸時拋出異常。

public final class LimitedOutputStream extends FilterOutputStream { 
    private final long maxBytes; 
    private long  bytesWritten; 
    public LimitedOutputStream(OutputStream out, long maxBytes) { 
     super(out); 
     this.maxBytes = maxBytes; 
    } 
    @Override 
    public void write(int b) throws IOException { 
     ensureCapacity(1); 
     super.write(b); 
    } 
    @Override 
    public void write(byte[] b) throws IOException { 
     ensureCapacity(b.length); 
     super.write(b); 
    } 
    @Override 
    public void write(byte[] b, int off, int len) throws IOException { 
     ensureCapacity(len); 
     super.write(b, off, len); 
    } 
    private void ensureCapacity(int len) throws IOException { 
     long newBytesWritten = this.bytesWritten + len; 
     if (newBytesWritten > this.maxBytes) 
      throw new IOException("File size exceeded: " + newBytesWritten + " > " + this.maxBytes); 
     this.bytesWritten = newBytesWritten; 
    } 
} 

你現在當然必須手動設置Writer/OutputStream鏈。

final long SIZE_1GB = 1073741824L; 
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
     new LimitedOutputStream(Files.newOutputStream(path), SIZE_1GB), 
     StandardCharsets.UTF_8))) { 
    // 
} 
-1

IIUC,有多種方法可以做到這一點。

  1. 保持將數據寫入卡盤並刷新它,並在每次刷新後繼續檢查文件大小。
  2. 使用log4j(或一些日誌框架),它可以讓我們在一定的大小或時間或某個其他觸發點後滾動到新文件。
  3. 雖然BufferedReader很棒,但是在java中有一些新的API可以使它更快。 Fastest way to write huge data in text file Java
2

在編寫行的情況下,對於1 GB的確切字節非常困難。每行可能包含未知數量的字節。我假設你想在文件中逐行寫入數據。

但是,您可以在將行寫入文件之前檢查行數有多少,另一種方法是在寫入每行之後檢查文件大小。

以下基本示例每次寫入同一行。這裏這只是一個測試!文本使用UTF-8編碼在文件上佔用21個字節。最終在49次寫入後達到1029字節並停止寫入。

public class Test { 

    private static final int ONE_KB = 1024; 

    public static void main(String[] args) { 
     File file = new File("D:/test.txt"); 

     try (BufferedWriter writer = Files.newBufferedWriter(file.toPath())) { 
      while (file.length() < ONE_KB) { 
       writer.write("This is just a test !"); 
       writer.flush(); 
      } 
      System.out.println("1 KB Data is written to the file.!"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

正如你可以看到,我們已經寫出來1KB的限制如上程序寫入1029個字節和不小於1024個字節。

第二種方法是在寫入文件之前根據特定的編碼檢查字節。

public class Test { 

    private static final int ONE_KB = 1024; 

    public static void main(String[] args) throws UnsupportedEncodingException { 
     File file = new File("D:/test.txt"); 
     String data = "This is just a test !"; 
     int dataLength = data.getBytes("UTF-8").length; 

     try (BufferedWriter writer = Files.newBufferedWriter(file.toPath())) { 
      while (file.length() + dataLength < ONE_KB) { 
       writer.write(data); 
       writer.flush(); 
      } 
      System.out.println("1 KB Data written to the file.!"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 

} 

在這種方法中,我們在它之前寫入文件校驗字節的長度。所以,它會寫1008字節,它將停止寫入。

問題有兩種方法,

  • 寫入和檢查:你也許結束了一些額外的字節,文件大小可能會越過極限
  • 檢查並寫:您可能必須小於該限制字節如果下一行有很多數據。你應該小心編碼。

不過,也有其他的方法來做到這一點的驗證與一些第三方庫像阿帕奇IO,我覺得它更麻煩那麼傳統的Java方法。

0
int maxSize = 1_000_000_000; 
Charset charset = StandardCharsets.UTF_F); 

int size = 0; 
int lineCount = 0; 
while (lineCount < lines.length) { 
    long size2 = size + (lines[lineCount] + "\r\n").getBytes(charset).length; 
    if (size2 > maxSize) { 
     break; 
    } 
    size = size2; 
    ++lineCount; 
} 

List<String> linesToWrite = lines.substring(0, lineCount); 
Path path = Paths.get("D:/test.txt"); 
Files.write(path, linesToWrite , charset); 

或在解碼只有一次有點快:

int lineCount = 0; 
try (FileChannel channel = new RandomAccessFile("D:/test.txt", "w").getChannel()) { 
    ByteBuffer buf = channel.map(FileChannel.MapMode.WRITE, 0, maxSize); 
    lineCount = lines.length; 
    for (int i = 0; i < lines.length; i++) { 
     bytes[] line = (lines.get(i) + "\r\n").getBytes(charset); 
     if (line.length > buffer.remaining()) { 
      lineCount = i; 
      break; 
     } 
     buffer.put(line); 
    } 
}