Java IO 教程

1 Java IO: Byte & Char Arrays

1.1 通过 InputStream 或 Reader 读取数组

要使这样的组件从数组中读取数据,必须将字节或字符数组包装在ByteArrayInputStream 或CharArrayReader中。 这样,可以通过包装流或读取器读取数组中可用的字节或字符。 这里有一个简单的例子:

byte[] bytes = new byte[1024];

//write data into byte array...

InputStream input = new ByteArrayInputStream(bytes);

//read first byte
int data = input.read();
while(data != -1) {
    //do something with data

    //read next byte
    data = input.read();
}

对 char 数组执行同样的操作与这个示例非常类似。 只需在 CharArrayReader 中包装 char 数组,就可以开始了。

1.2 通过 OutputStream 或 Writer 写入数组

也可以将数据写入 ByteArrayOutputStream 或 CharArrayWriter。 你所要做的就是创建一个 ByteArrayOutputStream 或者 CharArrayWriter,然后把你的数据写到它上面,就像你写给其他任何数据流或者作者一样。 一旦所有数据都写入到它,只需调用 toByteArray ()或 toCharArray 方法,所有写入的数据都以数组形式返回。 这里有一个简单的例子:

ByteArrayOutputStream output = new ByteArrayOutputStream();

output.write("This text is converted to bytes".getBytes("UTF-8"));

byte[] bytes = output.toByteArray();

对 char 数组执行同样的操作与这个示例非常类似。 只需在 CharArrayWriter 中包装 char 数组,就可以开始了。

2 Java IO: Readers and Writers

Reader

Java reader 是 java io api 中所有 Reader 的基类。 子类包括 BufferedReader、 PushbackReader、 InputStreamReader、 StringReader 和其他几个子类。 下面是一个简单的 Java i / o 阅读器例子:

    Reader reader = new FileReader("c:\\data\\myfile.txt");

    int data = reader.read();
    while(data != -1){
        char dataChar = (char) data;
        data = reader.read();
    }

请注意,尽管 InputStream 每次返回一个字节,这意味着值介于0和255之间(如果流没有更多数据,则返回 -1) ,但 Reader 每次返回一个字符,这意味着值介于0和65535之间(如果流没有更多数据,则返回 -1)。 这并不一定意味着 Reader 每次从所连接的源中读取两个字节。 它可以一次读取一个或多个字节,这取决于所读取文本的编码。

Combining Readers With InputStreams

可以与 InputStream 组合使用。 如果您有一个 InputStream 并希望从中读取字符,可以将其封装在 InputStreamReader 中。 将 InputStream 传递给 InputStreamReader 的构造函数,如下所示:

Reader reader = new InputStreamReader(inputStream);

在构造函数中,您还可以指定使用哪个字符集来解码文本等。 在 InputStreamReader 的文本中有更多关于这一点的内容。

Writer

Java writer 类是 java io api 中所有 Writers 的基类。 子类包括 BufferedWriter 和 PrintWriter 等。 下面是一个简单的 Java IO Writer 例子:

Writer writer = new FileWriter("c:\\data\\file-output.txt");

writer.write("Hello World Writer");
writer.close();

Combining Writers With OutputStreams

一个 Java Writer 可以像 Readers 和 InputStream 一样与 OutputStream 结合。 在 OutputStreamWriter 中包装 OutputStream,并将写入 Writer 的所有字符传递到 OutputStream。 下面是一个 OutputStreamWriter 的例子:

Writer writer = new OutputStreamWriter(outputStream);

Combining Readers and Writers

就像数据流一样,Reader 和 Writer 的数据流可以结合成链,从而实现更有趣的 i / o。 它的工作原理就像把 Reader 和 InputStream 结合起来,或者把 Writer 和 OutputStream 结合起来。 例如,可以通过在 BufferedReader 中包装 Reader 或在 BufferedWriter 中包装 Writer 来实现缓冲。 这里有两个例子:

Reader reader = new BufferedReader(new FileReader(...));

Writer writer = new BufferedWriter(new FileWriter(...));

3. Java InputStream

类,Java.io.Inputstream,表示一个有序的字节流。 换句话说,您可以将来自 java inputStream 的数据读取为一个有序的字节序列。 这在从文件中读取数据或通过网络接收数据时非常有用。 Java inputstream 类是 javaioapi 中所有输入流的基类(超类)。 Inputstream 的每个子类通常都有非常特定的用途,但是可以用作 InputStream。

子类是:

ByteArrayInputStream FileInputStream PipedInputStream BufferedInputStream FilterInputStream PushbackInputStream DataInputStream ObjectInputStream SequenceInputStream

InputStreams and Sources

输入流和源代码 一个 Java InputStream 通常连接到一些数据源,比如文件、网络连接、管道等。 这一点在 Java IO 概述文本中也有更详细的解释。 的用于读取基于字节的数据,一次读取一个字节。 下面是一个 Java InputStream 的例子,它从一个文件中读取所有字节:

InputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");

int data = inputstream.read();
while(data != -1) {
  //do something with data...
  doSomethingWithData(data);

  data = inputstream.read();
}
inputstream.close();

此示例创建一个新的 FileInputStream 实例。 Fileinputstream 是 InputStream 的子类,因此可以安全地将 FileInputStream 的实例分配给 InputStream 变量(InputStream 变量)。

Inputstream 的 read ()方法返回一个 int,其中包含所读取的字节的字节值。 下面是一个 InputStream read ()示例:

int data = inputstream.read();

要读取 javainputstream 中的所有字节,必须持续读取,直到返回值-1。 这个值意味着没有更多的字节可以从 InputStream 读取。 下面是一个从 Java InputStream 读取所有字节的例子:

int data = inputStream.read();
while(data != -1) {
    // do something with data variable

    data = inputStream.read(); // read next byte
}

Inputstream 的子类可能有可选择的 read ()方法。 例如,DataInputStream 允许您使用相应的方法 readBoolean ()、 readDouble ()等读取 Java 原语,如 int、 long、 float、 double、 boolean 等。

End of Stream

如果 read ()方法返回-1,则已经到达流的末尾,这意味着在 InputStream 中不再有要读取的数据。 也就是说,-1作为 int 值,而不是-1作为 byte 或 short 值。 这是有区别的! 当到达流的末尾时,可以关闭 InputStream。 read(byte[]) Inputstream 类还包含两个 read ()方法,它们可以将 InputStream 源的数据读取到字节数组中。 这些方法是: int read(byte[]) int read(byte[], int offset, int length) Read (byte [])方法将尝试根据数组的空间将尽可能多的字节读入作为参数给出的字节数组。 Read (byte [])方法返回一个 int,告诉实际读取了多少字节。 如果从 InputStream 中读取的字节数少于字节数组的空间,那么字节数组的其余部分将包含与开始读取之前相同的数据。 记住检查返回的整型数,看看实际上有多少字节被读入字节数组。 Read (byte [] ,int offset,int length)方法也将字节读入字节数组,但是从偏移字节开始读入数组,并从该位置将最大长度字节读入数组。 同样,read (byte [] ,int offset,int length)方法返回一个 int,告诉数组实际读入了多少字节,因此在处理 read 字节之前请记住检查这个值。 对于这两个方法,如果已经到达流的末尾,则该方法返回-1作为读取的字节数。 下面是使用 InputStream 的 read (byte [])方法的一个例子:

InputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");

byte[] data      = new byte[1024];
int    bytesRead = inputstream.read(data);

while(bytesRead != -1) {
  doSomethingWithData(data, bytesRead);

  bytesRead = inputstream.read(data);
}
inputstream.close();

首先,这个示例创建一个字节数组。 然后,它创建一个名为 bytesRead 的 int 变量来保存每次 read (byte [])调用的读取字节数,并立即将第一次 read (byte [])调用返回的值赋给 bytesRead。 在 while 循环中,调用 doSomethingWithData ()方法,传递数据字节数组以及将多少字节作为参数读入数组。 在 while 循环结束时,数据再次读入字节数组。 如何使用 read (byte [] ,int offset,int length)方法而不是 read (byte []) ,不需要太多的想象力。 几乎可以用 read (byte [] ,int offset,int length)调用替换 read (byte [])调用。

Read Performance

一次读取一个字节数组比一次从 javainputstream 读取一个字节要快。 通过读取一个字节数组而不是一次读取一个字节,这种差异很容易导致性能提高10倍或更多。 获得的准确加速度取决于您所读取的字节数组的大小,以及运行代码的计算机的操作系统、硬件等。 在决定之前,您应该研究目标系统的硬盘缓冲区大小等。 不过,缓冲区大小为8KB 及以上将提供很好的加速比。 然而,一旦你的字节数组超过了底层操作系统和硬件的容量,你不会从一个更大的字节数组得到更大的加速比。 为了找到最佳的字节数组大小,您可能需要试验不同的字节数组大小并测量读取性能。

Transparent Buffering via BufferedInputStream

您可以使用 Java BufferedInputStream 从 InputStream 中添加对字节数组的透明、自动读取和缓冲。 Bufferedinputstream 将一个字节块从基础 InputStream 读入一个字节数组。 然后,您可以从 BufferedInputStream 中一个接一个地读取字节,并且仍然可以获得大量的加速,这些加速来自于一次读取一个字节数组而不是一个字节。 下面是一个在 BufferedInputStream 中包装 Java InputStream 的例子:

InputStream input = new BufferedInputStream(
                      new FileInputStream("c:\\data\\input-file.txt"),
                        1024 * 1024        /* buffer size */
    );

注意,BufferedInputStream 是一个 InputStream 子类,可以在任何可以使用 InputStream 的地方使用。 mark() and reset() Inputstream 类有两个名为 mark ()和 reset ()的方法,InputStream 的子类可能支持也可能不支持这两个方法。 如果 InputStream 子类支持 mark ()和 reset ()方法,那么该子类应该重写 markSupported ()以返回 true。 如果 markSupported ()方法返回 false,则不支持 mark ()和 reset ()。 Mark ()在 InputStream 内部设置一个标记,用于标记流中迄今为止已经读取到的数据点。 然后,使用 InputStream 的代码可以继续从它中读取数据。 如果使用 InputStream 的代码希望返回到流中设置标记的点,则代码调用 InputStream 上的 reset ()。 Inputstream 然后“倒回”并返回到标记,并开始再次从该点返回(读取)数据。 这当然会导致某些数据从 InputStream 返回多次。 方法 mark ()和 reset ()方法通常用于实现解析器。 有时解析器可能需要在 InputStream 中提前读取,如果解析器没有找到它所期望的内容,它可能需要回退并尝试将读取的数据与其他内容进行匹配。

关闭 InputStream

使用完 Java InputStream 后,必须关闭它。 通过调用 InputStream close ()方法关闭 InputStream。 下面是一个打开 InputStream 的例子,从中读取所有数据,然后关闭它:

InputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");

int data = inputstream.read();
while(data != -1) {
  data = inputstream.read();
}
inputstream.close();

请注意 while 循环如何继续,直到从 InputStream read ()方法读取一个 -1值。 然后,while 循环退出,并调用 InputStream close ()方法。 上面的代码不是100% 健壮的。 如果在从 InputStream 读取数据时引发异常,则不会调用 close ()方法。 为了使代码更加健壮,您必须使用 Java try-with-resources 构造。 使用 javaio 类的正确异常处理也在我的 javaio 异常处理教程中进行了说明。 下面是一个使用 try-with-resources 构造关闭 Java InputStream 的示例:

try( InputStream inputstream = new FileInputStream("file.txt") ) {

    int data = inputstream.read();
    while(data != -1){
        data = inputstream.read();
    }
}

注意 InputStream 现在是如何在 try 关键字后面的括号中声明的。 这向 Java 发出信号,表明这个 InputStream 将由 try-with-resources 构造管理。 一旦正在执行的线程退出 try 块,inputstream 变量就会关闭。 如果从 try 块内部引发异常,则捕获异常,关闭 InputStream,然后重新引发异常。 这样就保证了当在 try-with-resources 块中使用 InputStream 时,它是关闭的。

将 InputStream 转换为 Reader

是一个基于字节的数据流。 您可能知道,javaioapi 还有一组基于字符的输入流,称为“ Readers”。 您可以使用 javainputstream 将 javainputstream 转换为 javareader。 你可以通过点击前面句子中的链接了解更多关于如何使用 InputStreamReader 的信息,但是这里有一个将 InputStream 转换为 InputStreamReader 的快速示例:

InputStream inputStream       = new FileInputStream("c:\\data\\input.txt");
Reader      inputStreamReader = new InputStreamReader(inputStream);

原文地址:Java IO 教程 (一) 

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值