java 操作字节_Java 字节流操作2

上篇文章Java 字节流操作介绍了java中基本的字节流操作,但是我们常常对于字符操作,如果使用字节流来实现输入输出就显得麻烦,我们可以使用字符流来实现对我们看得见的字符char进行操作,主要内容如下:

基本流(Reader/Writer)

转换流(InputStreamReader/OutputStreamEWriter)

文件字符流(FileReader/FileWriter)

字符数组流(charArrayReader/charArrayWriter)

缓冲字符流(BufferedReader/BufferedWriter)

装饰类(PrintWriter)

一、基本流

字节流的基本流是InputStream/OutputStream,这里的字符流的基本流是Reader/Writer,他们都是抽象类,想要实现更加复杂的操作就必须要子类来扩充。他们内部主要的就是read和write方法,实现单个字符及字符数组的读取的写入。此处就不再列出,我们将会从他们的子类中看看这些方法的实现。

二、转换流

InputStreamReader和OutputStreamWriter这两个类型流,在整个字符流中是十分重要的流,他们实现了和字节流的转换。先看看InputStreamReader:

private final StreamDecoder sd;

public InputStreamReader(InputStream in)

public InputStreamReader(InputStream in, String charsetName)

public InputStreamReader(InputStream in, Charset cs)

public InputStreamReader(InputStream in, CharsetDecoder dec)

public int read() throws IOException {

return sd.read();

}

public int read(char cbuf[], int offset, int length) throws IOException {

return sd.read(cbuf, offset, length);

}

首先定义了一个StreamDecoder 类型的常量(这是一个十分重要的成员),一堆构造方法通过不同的方式指定了外部传入的InputStream类型的参数和解码类型。我们看到,read方法中调用的是上述的sd常量(这是一个StreamDecoder类型的常量)的方法。这个StreamDecoder类实际上完成了将字节转换成char的操作。

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

InputStreamReader inr = new InputStreamReader(new FileInputStream("hello.txt"));

char[] chs = new char[100];

inr.read(chs);

System.out.println(chs);

inr.close();

}

}

上述代码展示了如何从文件中按照指定的解码方式读取出字符,OutputStreamWriter几乎是逆操作:

public void write(int c)

public void write(char cbuf[], int off, int len)

public void write(String str, int off, int len)

可以写int,可以写char数组,还可以写字符串(实际上还是调用了getchars方法获取该字符串的内置char数组,然后调用写数组的方法)。

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("hello.txt"));

ow.write("walker");

ow.close();

}

}

/*可以明显感知,对字符操作的简单直接*/

三、文件字符流

FileReader和FileWriter两个流,继承的是上述的两个转换流。内部的方法非常简单,只是几个构造方法而已。

public FileReader(String fileName) throws FileNotFoundException {

super(new FileInputStream(fileName));

}

public FileReader(File file) throws FileNotFoundException {

super(new FileInputStream(file));

}

public FileWriter(String fileName) throws IOException {

super(new FileOutputStream(fileName));

}

public FileWriter(String fileName, boolean append) throws IOException {

super(new FileOutputStream(fileName, append));

}

public FileWriter(File file) throws IOException {

super(new FileOutputStream(file));

}

从源代码中可以看出来,这两个文件流完全依赖父类。自己基本没有扩展父类,使用的方法都是父类的。你可以通过传文件的路径或者构建File类作为构造参数传入。

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

FileReader fr = new FileReader("hello.txt");

char[] chars = new char[1024];

fr.read(chars);

System.out.println(chars);

}

}

一样可以达到读取字符的效果,实际上上述代码可以转换为:

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

InputStreamReader ins = new InputStreamReader(new FileInputStream("hello.txt"));

char[] chars = new char[1024];

ins.read(chars);

System.out.println(chars);

}

}

//因为FIleReader的内部还是通过super调用父类的构造方法

四、字符数组流

和之前介绍的字节数组流类似,都是为了能提高效率防止内存浪费而设计的。看看我们上面的一段代码:

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

FileReader fr = new FileReader("hello.txt");

char[] chars = new char[1024];

fr.read(chars);

System.out.println(chars);

}

}

这段程序其实是不完善的,因为我们默认hello文件中的字符容量小于等于1024,那如果文件足够大,我们势必要创建更大的字符数组(这是一种浪费内存)。我们可以使用字符数组流来实现动态扩容,解决内存空间。上述代码可以改写:

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

FileReader fr = new FileReader("hello.txt");

int x = 0;

CharArrayWriter chw = new CharArrayWriter();

while ((x = fr.read()) != -1){

chw.write(x);

}

System.out.println(chw.toString());

chw.close();

}

}

这样,即使文件再大,我们也不会浪费很多内存空间。至于StingReader和StringWriter两个流其实是类似的,因为String的本质是char数组, 所以他们必然也是有数组作为最基本的操作。

五、缓冲字符流

字符的缓冲流和字节的缓冲流是类似的。都是装饰流。

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

BufferedReader bins = new BufferedReader(new FileReader("hello.txt"));

BufferedWriter bws = new BufferedWriter(new FileWriter("hello.txt",true));

int x;

while ((x = bins.read()) != -1){

System.out.println((char)x);

bws.write(x);

}

}

}

//缓冲读和缓冲写

六、PrintWriter

这是一个继承与Writer的流,他是一个非常方便的类,可以直接指定文件名作为参数,可以指定编码类型,还支持自动缓冲技术,可以自动转换多种基本类型为字符串形式写入文件中。在我们日常使用写入文件时,可以优先考虑使用该类。

protected Writer out;

private final boolean autoFlush;

//构造方法

public PrintWriter (Writer out) {

this(out, false);

}

public PrintWriter(OutputStream out) {

this(out, false);

}

public PrintWriter(String fileName) throws FileNotFoundException {

this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),

false);

public PrintWriter(File file) throws FileNotFoundException {

this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),

false);

}

//写入一个character

public void write(int c) {

try {

synchronized (lock) {

ensureOpen();

out.write(c);

}

}

catch (InterruptedIOException x) {

Thread.currentThread().interrupt();

}

catch (IOException x) {

trouble = true;

}

}

//写入一个字符串

public void write(String s) {

write(s, 0, s.length());

}

//重载print方法

public void print(boolean b) {

write(b ? "true" : "false");

}

public void print(char c) {

write(c);

}

public void print(int i) {

write(String.valueOf(i));

}

public void println() {

newLine();

}

public void println(int x) {

synchronized (lock) {

print(x);

println();

}

}

public void println(String x) {

synchronized (lock) {

print(x);

println();

}

}

上述代码中的print和println并非和我们的标准输出流(System.out.println)同义,这里的print表示写入到文件中。

public class Test_InputOrOutput {

public static void main(String[] args) throws IOException{

PrintWriter pw = new PrintWriter("hello.txt");

pw.println('x');

pw.close();

}

}

使用了PrintWriter写入到文件中,非常的简单方便,可以指定文件路径,File,OutputStream作为构造方法的形参。这一切的转换都封装了,自动提供缓冲流。这是一种比较好的输出流,在之后的使用中,如果遇到输出到文件,应该优先考虑PrintWriter。

标签:Java,字节,void,throws,char,new,操作,public,String

来源: https://www.cnblogs.com/Bkxk/p/11731792.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值