在字节流中输出数据主要使用OutputStream类完成,输入使用的是InputStream类。在字符流中输出主要是使用Writer类完成,输入主要是使用Reader类完成。
在Java中IO操作也是有相应步骤的,以文件的操作为例,主要的操作流程如下:
(1)使用File类打开一个文件
(2)通过字节流或者字符流的子类指定输出的位置
(3)进行读/写操作
(4)关闭输入/输出
①字节流:
字节流主要操作byte类型数据,以byte数组为准,主要操作类是OutputStream类和InputStream类。
OutputStream类是一个抽象类,如果要使用此类,则首先必须通过子类实例化对象。如果操作的是一个文件,则可以使用FileOutputStream类
OutputStream类的常用方法:
public void close() throws IOException 关闭输出流
public void flush() throws IOException 刷新缓冲区
public void write(byte[] b)throws IOException 将一个byte数组写入数据流
public void write(byte[] b,int off,int len)throws IOException 将一个指定范围的byte数组写入数据流
public abstract void write(int b) throws IOException 将一个字节数据写入数据流
追加新内容:
public FileOutputStream(File file)throws FileNotFoundException这个构造方法产生的流,第二次写入的东西会覆盖之前的,不能追加
public FileOutputStream(File file,boolean append)throws FileNotFoundException 在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容
public class Demo4 {
public static void main(String[] args) {
File file = new File("d:"+File.separator+"a.txt");
try {
OutputStream stream = new FileOutputStream(file,true);
String s = "Who am I?";
byte[] bytes = s.getBytes();
stream.write(bytes);
stream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
InputStream类是一个抽象类,如果要使用此类,则首先必须通过子类实例化对象。如果操作的是一个文件,则可以使用FileInputStream类
InputStream类的常用方法:
public int available()throws IOException可以取得输入文件的大小
public void close()throws IOException关闭输入流
public abstract int read() throws IOException读取内容,以数字的方式读取
public int read(byte[] b)throws IOException将内容读到byte数组中,同时返回读入的个数
public class Demo4 {
public static void main(String[] args) throws Exception {
File file = new File("d:"+File.separator+"a.txt");
InputStream inputStream = new FileInputStream(file);
byte[] b = new byte[(int) 1024];
int len = 0;
int temp = 0;
while ((temp=inputStream.read()) != -1) {
b[len] = (byte) temp;
len++;
}
inputStream.close();
System.out.println(new String(b,0,len));
}
}
②字符流:
在程序中一个字符等于两个字节,那么Java提供了Reader和Writer两个专门操作字符流的类。
字符输出流Writer:
Writer类的常用方法:(抽象类,文件写入内容,可使用子类FileWriter)
public abstract void close()throws IOException关闭输出流
public void write(String str) throws IOException将字符串输出
public void write(char[] cbuf)throws IOException将字符数组输出
public abstract void flush() throws IOException强制性清空缓存
在使用字符流操作时,也可以实现文件的追加功能,直接使用FileWriter类中的以下构造即可实现追加:
public FileWriter(File file,boolean append) throws IOException
将append的值设置为true,表示追加。
public class Demo5 {
public static void main(String[] args) throws Exception {
File file = new File("d:"+File.separator+"b.txt");
Writer writer = new FileWriter(file,true);
writer.write("\r\n今我来思,雨雪霏霏");
writer.close();
}
}
Reader的常用方法:(抽象类,读取文件内容,可使用子类FileReader)
public abstract void close() throws IOException关闭输入流
public int read()throws IOException读取单个字符
public int read(char[] cbuf)throws IOException将内容读取到字符数组中,返回读入的长度
public class Demo5 {
public static void main(String[] args) throws Exception {
File file = new File("d:"+File.separator+"b.txt");
Reader reader = new FileReader(file);
char[] c = new char[1024];
int len = 0;
int temp = 0;
while ((temp = reader.read()) != -1) {
c[len] = (char) temp;
len++;
}
System.out.println(new String(c,0,len));
}
}
③字节流和字符流的区别:
字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作的时候使用了缓冲区,通过缓冲区再操作文件。
证明方法:可以写两个Demo,一个是字节输出流,一个是字输出符流,在执行完之后不关闭流,会发现字节流操作完成,而字符流操作没完成。
什么叫缓冲区?
缓冲区可以简单地理解为一段特殊的内存区域。某些情况下,如果一个程序频繁的操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。如果在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法完成。
使用字节流好还是字符流好?
使用字节流更好,所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所以在开发中,字节流使用较为广泛。
实现复制功能:
public class Demo6 {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("输入的参数不正确");
System.out.println("例:java Copy 源文件路径 目标文件路径");
System.exit(1);
}
File f1 = new File(args[0]);
File f2 = new File(args[1]);
if (!f1.exists()) {
System.out.println("源文件不存在,请检查!");
System.exit(1);
}
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream(f1);
outputStream = new FileOutputStream(f2);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (inputStream != null && outputStream != null) {
int temp = 0;
try {
while ((temp = inputStream.read()) !=-1) {
outputStream.write(temp);
}
System.out.println("复制完成!");
}catch (Exception e) {
// TODO: handle exception
System.out.println("复制失败!");
}
finally {
try {
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
遇到的问题:eclipse中如何传值给args?
eclipse中给java应用传args参数的方法如下:
1、先写好Java代码,比如文件名为IntArrqy.java;
2、在工具栏或菜单上点run as下边有个Run Configuration;
3、在弹出窗口点选标签arguments;
4、把你想输入的参数写在program argumenst就可以了,多个参数使用空格隔开。
完成后点run即可通过运行结果看到参数使用情况了。
2.转换流-------OutputStreamWriter类与InputStreamReader类
OutputStreamWriter:是Writer的子类,将输出的字节流变为字符流,即将一个字节流的输出对象变为字符流输出对象。
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象。