使用固定字节数java读取文件
Reading a file using fixed number of bytes java
我正在编写一个程序来复制大文件,所以我想读取特定数量的字节并写入另一个文件。我想复制文件并获得相同的字节数。但我越来越多了。另外,我还希望文件的内容保持不变。我在这里做错了什么?如果有人能解释为什么我会收到这个额外的文字,那就太好了。
test.txt
|
1
2 3 4 |
sometext sometext sometext sometext
sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext |
实践.java
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class Practice{
public static void main(String[] args){ byte[] buffer = new byte[100]; try{ |
copy_test.txt
|
1
2 3 4 5 6 |
sometext sometext sometext sometext
sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext sometext metext sometext sometext sometext sometext sometext |
相关讨论
- 呃,你为什么不直接使用 Files.copy() 呢?
- 另外,您使用 InputStream 作为源,使用 Writer 作为目标?嗯?基本上你读的是苹果,但写的是橘子。
- @fge 因为它只是一个示例代码,实际上我正在将文件从服务器传输到客户端。所以我不能使用 Files.copy()。
- 取决于服务器。 java.nio.file API 允许 FileSystem 超越任何东西。例如见这里。请注意,Files.copy() 也可以从 InputStream 复制到 Path。
您的代码有几个问题:
- 您正在使用默认平台编码将二进制数据转换为文本(通过调用 new String(byte[]) 而不是指定编码
- 您正在使用默认平台编码将文本写入磁盘(使用 FileWriter)
- 您无条件地将整个缓冲区转换为文本,即使您的读取没有填充它 - 您可以通过使用 String 构造函数重载之一来解决这个问题,该重载采用偏移量和字节数,并传递 0和 b 用于参数,尽管我不会。使用 try-with-resources 语句。
- 您根本没有关闭输入流,如果抛出异常,您也没有关闭编写器。使用 try-with-resources 语句。
- 您正在捕获 Exception - 这通常是个坏主意。如果必须,捕获特定异常;就我个人而言,我只有很少的 catch 块 - 通常如果出现问题,则中止整个当前操作是合适的。 (当然,在某些情况下您可以重试等。)我知道这可能只是在您的示例代码中,而不是在您的真实代码中。
- 如果您只是尝试复制文件,则根本没有理由在二进制和文本之间进行转换 - 坚持使用输入流和输出流
- 如果你只是想复制一个文件,你可以使用 Files.copy 来避免编写任何代码,假设你使用的是 Java 7。(如果你不是,你应该是!)
如果您只想将 InputStream 复制到 OutputStream (并且您没有可用的实用程序库 - 这是许多库的一部分),您可以使用类似:
|
1
2 3 4 5 |
byte[] buffer = new byte[1024];
int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); } |
相关讨论
- 为什么缓冲区大小为 1024?
- @user3834119:为什么不呢?感觉像是内存使用和过多 IO 之间的合理平衡,尽管流中也可能存在缓冲。这是一个有点随意的数字——当然,你的 100 也是如此。
- @JonSkeet Files 库使用 8kb - 也许 1kb 有点小。尽管文件很小,但很可能完全没有区别。
- 1 kiB 太小了,真的。当今大多数现代架构的页面粒度为 8kiB。
- @fge - 页面粒度不直接相关。我们在这里谈论文件。使用太小的缓冲区进行读/写的问题是进行系统调用和上下文切换的开销。但是,是的,1kb 可能太小了。
- @StephenC 从某种意义上说,您仍然将内容写入页面并从页面读取(好吧,除非您使用 sendfile(2))。是的,系统调用开销也适合您。
- @fge - "...您仍然将内容写入页面并从页面中读取"。但这与性能有什么关系?如果读/写粒度是页面大小或更小,有什么区别?你还有同样数量的复制吗?该文件将以磁盘块的倍数传输到缓冲区缓存中/从缓冲区缓存中传输……无论读取和写入有多大/多小。
- @StephenC 简单:缓存抖动。您在页面上并不孤单。您与其他代码共享它。如果您占用的内容太少,您将与所有其他涉及该页面的代码竞争该页面。
- @fge - 我没有遵循你的论点。您是在谈论包含 buffer 引用的数组的页面吗?您还与哪些其他代码竞争?而且......如果你增加缓冲区大小,那实际上不会增加??缓存竞争吗?还是您在谈论 TLB 条目?
- 作为记录,我发现的信息表明 Linux 上的默认页面大小(在 x86 / x86_64 上)是 4k,而不是 8k。