使用固定字节数java读取文件

使用固定字节数java读取文件,java,file,byte,filestream,Java,File,Byte,Filestream,我正在编写一个程序来复制大文件,所以我想读取特定数量的字节并写入另一个文件。我想复制文件并获得相同的字节数。但我得到更多。另外,我还希望文件的内容保持不变。我做错了什么?如果有人能解释为什么我会收到这些额外的文本,那就太好了 test.txt sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext so

我正在编写一个程序来复制大文件,所以我想读取特定数量的字节并写入另一个文件。我想复制文件并获得相同的字节数。但我得到更多。另外,我还希望文件的内容保持不变。我做错了什么?如果有人能解释为什么我会收到这些额外的文本,那就太好了

test.txt

sometext sometext sometext sometext
sometext sometext sometext sometext
sometext sometext sometext sometext
sometext sometext sometext sometext
Practice.java

public class Practice{
    public static void main(String[] args){

    byte[] buffer = new byte[100];

    try{
        FileInputStream f = new FileInputStream("test.txt");
        FileWriter writer = new FileWriter("copy_test.txt");
        int b;
        while ((b=f.read(buffer)) != -1 )
            writer.write(new String(buffer));
        writer.close();
    } catch(Exception e){
        e.printStackTrace();
    }
 }
}
复制_test.txt

sometext sometext sometext sometext
sometext sometext sometext sometext
sometext sometext sometext sometext
sometext sometext sometext sometext
metext sometext sometext
sometext sometext sometext

您的代码有几个问题:

您正在使用默认平台编码,通过调用new Stringbyte[]而不是指定编码,将二进制数据转换为文本 您正在使用默认的平台编码通过FileWriter将文本写入磁盘 您正在无条件地将整个缓冲区转换为文本,即使您的读取没有填满它-您可以通过使用一个字符串构造函数重载来修复这一问题,该重载获取偏移量和字节数,并将0和b作为参数传递,尽管我不会这样做。使用try with resources语句。 您根本没有关闭输入流,如果抛出异常,您也没有关闭编写器。使用try with resources语句。 您正在捕获异常-这通常是个坏主意。如果必须,捕获特定的异常;就我个人而言,我只有很少的捕获块——一般来说,如果出现问题,中止当前的整个操作是合适的。当然,在某些情况下,您可以重试等。我理解这可能只是在这里的示例代码中,而不是在实际代码中。 如果您只是试图复制一个文件,那么根本没有理由在二进制和文本之间进行转换——请坚持使用输入流和输出流 如果您只是试图复制一个文件,那么可以使用来避免编写任何代码,假设您使用的是Java7。如果你不是,你应该是! 如果您只想将InputStream复制到OutputStream,而您没有可用的实用程序库-这是许多库的一部分,您可以使用以下工具:

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
    output.write(buffer, 0, bytesRead);
}

您的代码有几个问题:

您正在使用默认平台编码,通过调用new Stringbyte[]而不是指定编码,将二进制数据转换为文本 您正在使用默认的平台编码通过FileWriter将文本写入磁盘 您正在无条件地将整个缓冲区转换为文本,即使您的读取没有填满它-您可以通过使用一个字符串构造函数重载来修复这一问题,该重载获取偏移量和字节数,并将0和b作为参数传递,尽管我不会这样做。使用try with resources语句。 您根本没有关闭输入流,如果抛出异常,您也没有关闭编写器。使用try with resources语句。 您正在捕获异常-这通常是个坏主意。如果必须,捕获特定的异常;就我个人而言,我只有很少的捕获块——一般来说,如果出现问题,中止当前的整个操作是合适的。当然,在某些情况下,您可以重试等。我理解这可能只是在这里的示例代码中,而不是在实际代码中。 如果您只是试图复制一个文件,那么根本没有理由在二进制和文本之间进行转换——请坚持使用输入流和输出流 如果您只是试图复制一个文件,那么可以使用来避免编写任何代码,假设您使用的是Java7。如果你不是,你应该是! 如果您只想将InputStream复制到OutputStream,而您没有可用的实用程序库-这是许多库的一部分,您可以使用以下工具:

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
    output.write(buffer, 0, bytesRead);
}

为什么缓冲区大小为1024?@user3834119:为什么不?虽然流中也可能存在缓冲,但它感觉像是内存使用和过多IO之间的合理平衡。这是一个有点任意的数字——当然,和你的100一样。@jonsket文件库使用8kb——也许1kb有点小。虽然对于一个小文件来说,它很可能完全没有区别。1kib太小了,真的。当今大多数现代体系结构上的页面粒度为8kiB。@fge-页面粒度与此没有直接关系。我们在这里谈论的是文件。使用太小的缓冲区执行读/写操作的问题是执行系统调用和上下文切换时的开销。是的,1kb可能太小了。为什么缓冲区的大小是1024?@user3834119:为什么不呢?虽然流中也可能存在缓冲,但它感觉像是内存使用和过多IO之间的合理平衡。这是一个有点任意的数字——当然,和你的100一样。@jonsket文件库使用8kb——也许1kb有点小。虽然对于一个小文件来说,它很可能完全没有区别。1kib太小了,真的。当今大多数现代体系结构上的页面粒度为8kiB。@fge-页面粒度与此没有直接关系。我们在这里谈论的是文件。使用缓冲区执行读/写操作的问题
太小的开销是系统调用和上下文切换的开销。但是是的,1kb可能太小了。呃,为什么不直接使用呢?另外,您使用InputStream作为源,使用Writer作为目标?嗯?基本上你在读苹果,但在写橘子。@fge因为它;这只是一个示例代码,实际上我正在将文件从服务器传输到客户端。因此,我无法使用Files.copy。取决于服务器。file API允许文件系统覆盖任何内容。例如。请注意。呃,为什么不直接使用?另外,您使用InputStream作为源,使用Writer作为目标?嗯?基本上你在读苹果,但在写橘子。@fge因为它;这只是一个示例代码,实际上我正在将文件从服务器传输到客户端。因此,我无法使用Files.copy。取决于服务器。file API允许文件系统覆盖任何内容。例如。请注意这一点。