Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在用java编写时限制文件大小_Java_File_Bufferedwriter - Fatal编程技术网

在用java编写时限制文件大小

在用java编写时限制文件大小,java,file,bufferedwriter,Java,File,Bufferedwriter,我需要将文件大小限制为1 GB,同时最好使用BufferedWriter进行写入 是否可以使用BufferedWriter或我必须使用其他库 像 IIUC,有多种方法可以做到这一点 继续在卡盘中写入数据并刷新,每次刷新后继续检查文件大小 使用log4j(或一些日志框架),它可以让我们在特定的大小、时间或其他触发点之后滚动到新文件 虽然BufferedReader很棒,但是java中有一些新的API可以让它更快 您始终可以编写自己的OutputStream,以限制写入的字节数 以下假设您希望在超出

我需要将文件大小限制为1 GB,同时最好使用
BufferedWriter
进行写入

是否可以使用
BufferedWriter
或我必须使用其他库


IIUC,有多种方法可以做到这一点

  • 继续在卡盘中写入数据并刷新,每次刷新后继续检查文件大小
  • 使用log4j(或一些日志框架),它可以让我们在特定的大小、时间或其他触发点之后滚动到新文件
  • 虽然BufferedReader很棒,但是java中有一些新的API可以让它更快
    您始终可以编写自己的
    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))) {
        //
    }
    

    在写行的情况下,将字节精确到1GB是非常困难的。每行可能包含未知数量的字节。我假设您想在文件中逐行写入数据

    不过,您可以在将行写入文件之前检查行有多少字节,另一种方法是在写入每行之后检查文件大小

    下面的基本示例每次写一行。这只是一个测试!文本以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();
            }
        }
    }
    
    公共类测试{
    私有静态final int ONE_KB=1024;
    公共静态void main(字符串[]args){
    File File=新文件(“D:/test.txt”);
    try(BufferedWriter=Files.newBufferedWriter(file.toPath())){
    while(file.length()<1KB){
    写(“这只是一个测试!”);
    writer.flush();
    }
    System.out.println(“1KB的数据写入文件!”;
    }捕获(IOE异常){
    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();
            }
    
        }
    
    }   
    
    公共类测试{
    私有静态final int ONE_KB=1024;
    公共静态void main(字符串[]args)引发UnsupportedEncodingException{
    File File=新文件(“D:/test.txt”);
    String data=“这只是一个测试!”;
    int dataLength=data.getBytes(“UTF-8”).length;
    try(BufferedWriter=Files.newBufferedWriter(file.toPath())){
    while(file.length()+数据长度<1KB){
    writer.write(数据);
    writer.flush();
    }
    System.out.println(“写入文件的1KB数据!”;
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    }
    }   
    
    在这种方法中,我们在将字节写入文件之前检查字节的长度。因此,它将写入1008字节,并将停止写入

    两种方法都存在问题

    • 写和检查:您可能会得到一些额外的字节,文件大小可能会超过限制
    • 检查并写入:如果下一行中有大量数据,则字节数可能少于限制。你应该注意编码
    然而,还有其他方法可以通过一些第三方库(如ApacheIO)进行验证,我发现这比传统的java方法更麻烦

    intmaxsize=1_000_000;
    
    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);
    
    字符集字符集=标准字符集.UTF\u F); int size=0; int lineCount=0; while(lineCountmaxSize){ 打破 } 尺寸=尺寸2; ++行数; } List linesToWrite=行。子字符串(0,行计数); Path Path=Path.get(“D:/test.txt”); write(路径、linesToWrite、字符集);
    或者在只解码一次的情况下速度稍微快一点:

    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);
        }
    }
    
    int lineCount=0;
    try(FileChannel channel=newrandomAccessFile(“D:/test.txt”,“w”).getChannel()){
    ByteBuffer buf=channel.map(FileChannel.MapMode.WRITE,0,maxSize);
    lineCount=lines.length;
    对于(int i=0;ibuffer.remaining()){
    lineCount=i;
    打破
    }
    缓冲区。放置(行);
    }
    }
    
    选中此项:…将文件大小限制为1GB,以便将内容写入1GB?或者仅当内容小于1 GB时才写入内容?要在内容达到1 GB时停止写入吗@TAskStop,如丢弃任何额外数据,或抛出异常“文件太大”?但如何确定文件大小是否达到1GB
    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);
        }
    }