黑马程序员-java-IO与File

来源:互联网 发布:网络推广赚钱项目 编辑:程序博客网 时间:2024/06/08 18:59
---------------------- android培训、java培训、期待与您交流! ----------------------
  IO流用来处理设备之间的数据传输,java对数据的操作是通过流的方式,数据可以在硬盘和内存中,
流按数据分为两种:字节流和字符流
按方向分为:输入流与输出流

字节流是以字节作为流中元素的基本类型,每次读或者写的最小单位是一个字节,
字节输入流类是InputStream类以及子类,输出流是OutputStream以及子类。
字符流是以字符作为流中元素的基本类型,每次读写的最小单位是一个字符,
即2字节的Unicode码,字符流融合了编码表,字符输入流为Reader类以及其子类,输出流类是Writer以及其子类。

用IO流要明确源和目的:
 源:输入流 InputStream Reader
 目的:输出流OutputStream Writer
 
操作的数据是否是纯文本:
是:字符流
不是:字节流
二进制格式只要不能确定是纯文本的用: InputStream, OutputStream
是文件用 FileInputStream, FileOutputStream, FileReader, FileWriter
FileReader和FileInputStream用的时候文件必须已经存在在指定目录下

要格式化输出用 PrintStream, PrintWriter
是字节数组 byte[]用ByteArrayInputStream, ByteArrayOutputStream

遇到字节和字符数组,我们一般把他们转化为String,下面是String的4个构造方法
public String(byte[] bytes)
public String(byte[] bytes,int offset,int length)
public String(char[] value)
public String(char[] value,int offset,int count)

String可以通过下面2个方法转化成字节和字符数组:
public byte[] getBytes()
char[] toCharArray()

对象的输入输出用ObjectInputStream, ObjectOutputStream
进程间的通信用PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
合并文件流用SequenceInputStream

遇到从Stream到Reader,Writer的转换,我们用InputStreamReader和OutputStreamWriter
InputStreamReader和OutputStreamWriter两个流在构造的时候主要可以加入字符编码方式,如:
new InputStreamReader(new FileInputStream("d:/hello.txt"), "utf-8"),
new OutputStreamWriter(new FileOutputStream("d:/hello.txt"), "utf-8")

要想加入缓冲用BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
下面举例应用:
读取d盘下的Demo.java文件
  FileReader fr = new FileReader("d:/Demo.java");
  char[] achar = new char[1024];
  int num = 0;
  while (-1 != (num=fr.read(achar)))
  {
   System.out.println(new String(achar,0,num));
  }
  fr.close();
 还可以这样读:
  FileReader fr = new FileReader("d:/Demo.java");
  int ch=0;
  while(-1!=(ch=fr.read()))
  {
   System.out.print((char)ch);
  }
   fr.close();

  带缓冲区的读入:
  FileReader fr = new FileReader("d:/Demo.java");
  BufferedReader br = new BufferedReader(fr);
  String str;
  while (null != (str = br.readLine()))//readLine()读一行,并不读取换行符
  {
   System.out.println(str);
  }
  br.close();


向d盘下的hello.txt文件写入字符串,并处理IO异常
   FileWriter f = null;
  try
  {
   f = new FileWriter("d:/hello.txt",true);//追加内容,并不覆盖文件
   String str = "hello world welcome";
   f.write(str);
  }
  catch (Exception e)
  {
     e.printStackTrace();
  }
      finally
  {
   try
   {
    if (f != null)
     f.close();
   }
   catch (Exception e)
   {
        e.printStackTrace();
   }
  }
 }

 还可以一个字符一个字符写入:
   String str = "hello world welcome ";
  char[] buffer = new char[str.length()];
  str.getChars(0, str.length(), buffer, 0);
  FileWriter f = new FileWriter("d:/hello.txt");
  for (int i = 0; i < buffer.length; i++)
  {
   f.write(buffer[i]);
  }
  f.close();

  带缓冲区的写入:
   FileWriter f = new FileWriter("d:/hello.txt", true);// 追加内容,并不覆盖文件
  BufferedWriter bw = new BufferedWriter(f);
  bw.write("hello");
  bw.newLine();// 换行符
  bw.write("world");
  bw.newLine();
  bw.write("comeon");
  bw.close();

 下面程序实现对图片文件的拷贝:
  InputStream in = new FileInputStream("d:/11.jpg");
   byte[] b = new byte[200];
   int length = 0;
   OutputStream os;
   os = new FileOutputStream("d:/22.jpg");
   while (-1 != (length = in.read(b)))
   {
    os.write(b, 0, length);
   }
   in.close();
   os.close();
 还可以带缓冲区的拷贝:
   FileInputStream fis = new FileInputStream("d:/11.jpg");
  BufferedInputStream br = new BufferedInputStream(fis);
  byte[] buf = new byte[1024];
  int length = 0;
  FileOutputStream fos = new FileOutputStream("d:/22.jpg");
  BufferedOutputStream os = new BufferedOutputStream(fos);
       while (-1 != (length = br.read(buf)))
  {
   os.write(buf, 0, length);

  }
       br.close();
       os.close();

下面是ByteArrayOutputStream的一个应用,从内存读取字符串,
存到另一个字节数组打印,也可以writeTo到OutputStream
   String str = "welcome";
  byte[] abyte = str.getBytes();
  ByteArrayOutputStream b = new ByteArrayOutputStream();
  b.write(abyte);
  byte[] buf = b.toByteArray();
  for (int i = 0; i < buf.length; i++)
  {
   System.out.print(" " + (char) buf[i]);
  }
  OutputStream out = new FileOutputStream("d:/hello.txt");
  b.writeTo(out);
  out.close();

  InputStream有个方法available可以读取输入流当前可读取的字节数,
 就可创建一个已知大小的字节数组,看应用:
   FileInputStream fis = new FileInputStream("d:/Demo.java");
  byte[] buf = new byte[fis.available()];
  fis.read(buf);
  System.out.println(new String(buf));
  fis.close();
 
下面的程序实现从键盘录入,当敲回车时打印出来,录入over程序结束
    InputStream in = System.in;
  StringBuilder sb = new StringBuilder();
  while (true)
  {
   int ch = in.read();
   if (ch == '\r')
    continue;
   if (ch == '\n')
   {
    String s = sb.toString();
    if ("over".equals(s))
     break;
    System.out.println(s);
    sb.delete(0, sb.length());
   }
   else
    sb.append((char) ch);
     }
    
下面通过流的组合从键盘录入数据,打印在控制台
  InputStreamReader isr = new InputStreamReader(System.in);
  BufferedReader br = new BufferedReader(isr);
  OutputStreamWriter osw = new OutputStreamWriter(System.out);
  BufferedWriter bw = new BufferedWriter(osw);
  String line = null;
  while (null != (line = br.readLine()))
  {
   bw.write(line);
   bw.newLine();
   bw.flush();
  }
  br.close();

下面代码是ObjectOutputStream和ObjectInputStream的应用,写3个对象到
hello.txt文件中,然后再读取出来。
public class SerializableTest1
{
 public static void main(String[] args) throws Exception
 {
  Person11 p1 = new Person11(20, "zhangsan", 4.55);
  Person11 p2 = new Person11(50, "lisi", 4.67);
  Person11 p3 = new Person11(10, "wangwu", 17.78);
  FileOutputStream fos = new FileOutputStream("d:/hello.txt");
  ObjectOutputStream oos = new ObjectOutputStream(fos);
  oos.writeObject(p1);
  oos.writeObject(p2);
  oos.writeObject(p3);
  oos.close();
  System.out.println("--------------------");
  FileInputStream fis = new FileInputStream("d:/hello.txt");
  ObjectInputStream ois = new ObjectInputStream(fis);
  Person11 p = null;
  for (int i = 0; i < 3; i++)
  {
   p = (Person11) ois.readObject();
   System.out.println(p.age + "," + p.name + "," + p.height);
  }
  ois.close();
 }
}
class Person11 implements Serializable//序列化要实现Serializable接口
{
 int age;
 String name;
 double height;
 public Person11(int age, String name, double height)
 {
  this.age = age;
  this.name = name;
  this.height = height;
 }
}

 另外,如果序列化写入或读取对象时,想要控制对象写入的信息,
 就要自己实现writeObject,readObject方法,看下面例子只写入
 Person对象的name和age
public class SerializableTest2
{
 public static void main(String[] args) throws Exception
 {
  Person2 p1 = new Person2(20, "zhangsan", 4.55);
  Person2 p2 = new Person2(50, "lisi", 4.67);
  Person2 p3 = new Person2(10, "wangwu", 17.78);
  FileOutputStream fos = new FileOutputStream("d:/haha.txt");
  ObjectOutputStream oos = new ObjectOutputStream(fos);
  oos.writeObject(p1);
  oos.writeObject(p2);
  oos.writeObject(p3);
  oos.close();
  System.out.println("--------------------");
  FileInputStream fis = new FileInputStream("d:/haha.txt");
  ObjectInputStream ois = new ObjectInputStream(fis);
  Person2 p = null;
  for (int i = 0; i < 3; i++)
  {
   p = (Person2) ois.readObject();
   System.out.println(p.age + "," + p.name + "," + p.height);
  }
  ois.close();
 }
}
class Person2 implements Serializable
{
 int age;
 String name;
 double height;
 public Person2(int age, String name, double height)
 {
  this.age = age;
  this.name = name;
  this.height = height;
 }
//提供writeObject readObject 序列化内容就要具体自己实现
private void writeObject(java.io.ObjectOutputStream out) throws IOException
 {
  out.writeInt(age);
  out.writeUTF(name);
  System.out.println("write object");
 }
private void readObject(java.io.ObjectInputStream in) throws IOException,
 ClassNotFoundException
 {
  age = in.readInt();
  name = in.readUTF();
  System.out.println("read object");
 }
}

 打印流PrintStream和PrintWriter可以将各种数据类型的数据都原样打印,
 而且可以直接与文件相关联。
 下面看一个PrintWriter的应用,键盘录入内容,打印到hello.txt文件中,
PrintWriter追加true表示自动刷新。
注意如果直接 new PrintWriter("d:/hello.txt"),不会自动刷新,
把文件封装到流里才会自动刷新。
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String str = null;
//PrintWriter pw = new PrintWriter(System.out, true);//true,自动刷新
//PrintWriter pw = new PrintWriter("d:/hello.txt");
PrintWriter pw = new PrintWriter(new FileWriter("d:/hello.txt"),true);
while (null != (str = br.readLine()))
{
 if("over".equals(str))
  break;
 pw.println(str);//println刷新
}
br.close();
pw.close();

看下面的代码可以将数组异常信息输出到log.txt文件中:
try
  {
   int[] a = new int[] { 2, 4, 5 };
   System.out.println(a[5]);
  }
  catch (Exception e)
  {
   e.printStackTrace(new PrintStream(new FileOutputStream("d:/log.txt")));
  }

 下面的代码可以将系统的属性信息打印到d盘的properties文件中
   Properties p = System.getProperties();
   p.list(new PrintStream("d:/properties.txt"));

 下面看一下SequenceInputStream流的应用,它可以将多个文件内容
 一起合并读入到另一个文件中。
  Vector<FileInputStream> v = new Vector<FileInputStream>();
  v.add(new FileInputStream("d:/j1.txt"));
  v.add(new FileInputStream("d:/j2.txt"));
  v.add(new FileInputStream("d:/j3.txt"));
  Enumeration<FileInputStream> en = v.elements();
  SequenceInputStream sis = new SequenceInputStream(en);
  FileOutputStream fos = new FileOutputStream("d:/j4.txt");
  byte[] buf = new byte[1024];
  int len = 0;
  while ((len = sis.read(buf)) != -1)
  {
   fos.write(buf, 0, len);
  }
  fos.close();
  sis.close();

有合并就有分割,看下面的例子可把一个文件分成任意
大的任意等份。
如果mm.mp3文件为5M,下面程序分割文件每份为2M,分成3份
FileInputStream fis = new FileInputStream("d:/mm.mp3");
FileOutputStream fos = null;
byte[] buf = new byte[1024 * 1024];
int len = 0;
int count = 1;
while (fis.available() > 0)
{
 fos = new FileOutputStream("d:/www/" + (count++) + ".mp3");
 int mark = 0;
 while ((len = fis.read(buf)) != -1)
 {
  fos.write(buf, 0, len);
  mark++;
  if (mark == 2)
   break;
 }
 fos.close();
}
 
  下面谈一下字符编码的问题:
编码: 字符串变成字节数组
解码 : 字节数组变成字符串
 String -- byte[] str.getBytes(charsetName);
 byte[] -- String: new String(byte[],charsetName);
 
假如一个txt文件是按utf-8来编码的,那我们从硬盘读取该文件
的时候,也应该指定编码为utf-8,
InputStreamReader isr = new InputStreamReader(new FileInputStream("d:/as.txt"), "utf-8");
当然,我们向一个文件输出内容的时候,也可以指定编码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/as.txt"), "UTF-8");
osw.write("你好啊");

我们知道流是用来操作数据的,而数据的主要体现形式就是文件,文件又包含了很多
自己的属性和行为信息。java中的File类用来将文件和文件夹封装成对象,方便对文件
和文件夹的属性信息进行操作。
File常用方法:
createNewFile() 文件已经存在,则不创建
boolean delete()
void deleteOnExit() 在程序退出时删除文件
boolean canExecute() 文件是否可以执行
boolean mkdir() 创建一级目录
boolean mkdirs() 创建多级目录
boolean exists() 文件是否存在
boolean isDirectory()
boolean isFile()
boolean isHidden() 注意一般不要拿硬盘中隐藏的文件
boolean isAbsolute()

下面是File类应用举例:
 File file = new File("d:/aa.txt");//绝对路径
 //File file = new File("aa.txt");//相对路径
 file.createNewFile();
 System.out.println(file.exists());

   File file = new File("c:/444");
  file.mkdir();
  File file2 = new File(file, "hello.txt");
  file2.createNewFile();

下面程序打印abc文件夹下所有文件和文件夹的名字
  File file = new File("c:/abc");
  File[] files = file.listFiles();
  for (File f : files)
  {
   System.out.println(f.getName());
  }

下面程序打印abc文件夹下后缀名为.txt文件的名字
  File file = new File("C:\\abc");
  String[] names = file.list(new FilenameFilter()
  {
   public boolean accept(File dir, String name)
   {
    if (name.endsWith(".txt"))
    {
     return true;
    }
    return false;
   };
  });
  for (String name : names)
  {
   System.out.println(name);
  }

下面程序打印abc文件夹下所有文件的扩展名字
 File file = new File("d:/abc");
  File[] files = file.listFiles();
  for (File f : files)
  {
   String str = f.getName();
   int lastIndex = str.lastIndexOf(".");
   String exname = str.substring(lastIndex + 1);
   System.out.println("文件的扩展名为:" + exname);

  }

下面程序采用递归打印bb文件夹下所有文件及子文件的名字
public class Test
{
  public static void showDir(File file, int level)
 {
    String p = " ";
  for (int i = 0; i < level; i++)
  {
   p = p + "   ";
  }
  File[] files = file.listFiles();
  for (File f : files)
  {
   System.out.println(p + f.getName());
   if (f.isDirectory())
    showDir(f, level + 1);
  }
}
  public static void main(String[] args)
 {
  File file = new File("c:/bb");
  showDir(file, 0);
 }
}

下面程序采用递归删除abc文件下所有文件
public class DeleteTest
{
 public static void deleteAll(File file)
 {
  if (file.isFile() || file.list().length == 0)
  {
   file.delete();
  }
  else
  {
   File[] files = file.listFiles();
   for (File f : files)
   {
    deleteAll(f);
    f.delete();
   }
  }
 }
 public static void main(String[] args)
 {
  deleteAll(new File("c:/abc"));
 }
}
 java中的IO和File都是很重要的内容,好了,关于这部分的内容
 就学习和总结到这了,谢谢。

---------------------- android培训、java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima
原创粉丝点击