一般在操作文件流时,不管是字节流还是字符流,都可以按照以下的方式进行。
1、使用File类找到一个文件
2、通过File类实例化字节流或字符流
3、进行字节(字符)的读写操作
4、关闭文件流
下面是2个例子,向文件中写入字符串并读出。
以字节流方式:
1 package zdxtest; 2 import java.io.*; 3 public class TestFile1 { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 //字节流输入输出,向一个文件写入内容然后读出 8 File f = new File("d:\\1.txt"); 9 FileOutputStream fos = null; 10 FileInputStream foi = null; 11 String sin = "今天是七月最后一天"; 12 //创建文件,如果目录下存在文件,先删除再创建 13 if (f.exists()) { 14 f.delete(); 15 try { 16 f.createNewFile(); 17 } catch (IOException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 } 22 else{ 23 try { 24 f.createNewFile(); 25 } catch (IOException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 } 30 //实例化字节流子类:FileOutputStream 31 try { 32 fos = new FileOutputStream(f); 33 } catch (FileNotFoundException e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 } 37 //以字节的方式写入文件并关闭流 38 byte[] b = sin.getBytes(); 39 try { 40 fos.write(b); 41 fos.close(); 42 } catch (IOException e) { 43 // TODO Auto-generated catch block 44 e.printStackTrace(); 45 } 46 //实例化字节流子类:FileInputStream 47 try { 48 foi = new FileInputStream(f); 49 } catch (FileNotFoundException e) { 50 // TODO Auto-generated catch block 51 e.printStackTrace(); 52 } 53 //以字节的方式读取文件并关闭流 54 byte[] c = new byte[1000]; 55 int l=0; 56 try { 57 /*l = foi.read(); 58 while(l!=-1){ 59 System.out.println(String.valueOf(l)); 60 l=foi.read(); 61 }*/ 62 l = foi.read(c); 63 foi.close(); 64 } catch (IOException e) { 65 // TODO Auto-generated catch block 66 e.printStackTrace(); 67 } 68 String o = new String(c); 69 System.out.println(o); //打印文件内容 70 System.out.println(l); //打印读取的字节数 71 72 } 73 74 }
运行后输出:
今天是七月最后一天
27
为什么是27个字节呢,因为我eclipse的默认编码方式是UTF-8,在UTF-8编码方式中,一个汉字是占有三个字节的,一共9个汉字,所以是27个字节。
再来看以字符流的方式实现:
1 package zdxtest; 2 import java.io.*; 3 4 public class FileTest2 { 5 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 File f = new File("d:\\2.txt"); 9 FileReader fr = null; 10 FileWriter fw = null; 11 String s = "明天是八月第一天"; 12 //创建文件,如果目录下存在文件,先删除再创建 13 if(f.exists()) 14 { 15 f.delete(); 16 try { 17 f.createNewFile(); 18 } catch (IOException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 } 23 else{ 24 try { 25 f.createNewFile(); 26 } catch (IOException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 } 31 //实例化字符流子类:FileWriter,以字符的方式写入文件并关闭流 32 try { 33 fw = new FileWriter(f); 34 fw.write(s); 35 fw.close(); 36 } catch (IOException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 //实例化字符流子类:FileReader,以字符的方式读取文件并关闭流 41 char [] b = new char[1000]; 42 int l = 0; 43 try { 44 fr = new FileReader(f); 45 l = fr.read(b); 46 } catch (IOException e) { 47 // TODO Auto-generated catch block 48 e.printStackTrace(); 49 } 50 System.out.println(new String(b)); //打印文件内容 51 System.out.println(l); //打印读取的字符数 52 } 53 54 }
运行输出:
明天是八月第一天
8
一共8个汉字,一个char存储一个汉字,所以是8个字符
另外的参考:
回顾字节流输入输出
Reader和Writer
Reader和Writer这两个抽象类主要用来读写字符流。
InputStreamReader是字节流通向字符流的桥梁
BufferedReader提供一个ReadLine()方法
OutputStreamWriter是字符流到字节流的桥梁
BufferedWriter也提供了一个很有用的方法,请看示例:
示例:
public static void main(String[] args) throws Exception{
//对文件的写入和对文件的读取
FileOutputStream fos = new FileOutputStream("1.txt");
//OutputStreamWriter这个函数的构造方法需要一个OutputStream对象
OutputStreamWriter osw = new OutputStreamWriter(fos);
//通常我们构造BufferedWriter去进行写入操作,是一个更有效的写入操作。参数需要Writer类型。
BufferedWriter bw = new BufferedWriter(osw);
bw.write("this is test BufferedWriter");
bw.close();
FileInputStream fis = new FileInputStream("1.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
}
示例:直接读取控制台的输入流
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String str = null;
while((str=br.readLine())!=null){
System.out.println(str);
}
br.close();
结果:
xiaohong
xiaohong
补充:字节流和字符流的区别
干货1:因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。
干货2:流分类:
1.Java的字节流
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。
2.Java的字符流
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。
InputStream,OutputStream,Reader,writer都是抽象类。所以不能直接new
干货3:在从字节流转化为字符流时,实际上就是byte[]转化为String时,
public String(byte bytes[], String charsetName)
有一个关键的参数字符集编码,通常我们都省略了,那系统就用操作系统的lang
而在字符流转化为字节流时,实际上是String转化为byte[]时,
byte[] String.getBytes(String charsetName)
也是一样的道理
一般使用BufferedWriter高校
public String to_upper(String str)
{
String str1=str.toUpperCase();
BufferedWriter writer = null;
File file = new File("d:\\dat\\"+ "aaa" + ".json");
//如果文件不存在,则新建一个
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//写入
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,false), "UTF-8"));
writer.write("aaa");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(writer != null){
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return str1;
}