关闭

黑马程序员_JavaIO输入与输出下

91人阅读 评论(0) 收藏 举报

----------- android培训java培训java学习型技术博客、期待与您交流! ------------

 

       File概述

File类:用来将文件或者文件夹封装成对象。方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。

示例:

import java.io.*;
class FileDemo
{
 public static void main(String[] args)
 {
  consMethod();
 }
 public static void consMethod()
 {
  //创建File对象,将a.txt封装成File对象。可以将已有的和不存在的文件或文件夹封装成File对象。
  File f1=new File("a.txt");
  File f2=new File("d:\\abc","b.txt");
  File d=new File("d:\\abc");
  File f3=new File(d,"c.txt");
  File f4=new File("d:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"z.txt");
  sop("f1:"+f1);
  sop("f2:"+f2);
  sop("f3:"+f3);
  sop("f4:"+f4);
 }
 public static void sop(Object obj)
 {
  System.out.println(obj);
 }
}

 

File类中常见方法:

1.创建:

boolean createNewFile():在指定位置创建文件。如果该文件已经存在,则不创建,返回false。

boolean mkdir():创建一级文件夹。

boolean mkdirs():创建多级文件夹。

2.删除:

boolean delete():删除失败返回false。如果文件正在被使用,则删除失败返回false。

void deleteOnExit():在程序退出时删除指定文件。

示例1:

import java.io.*;
class FileDemo1
{
 public static void main(String[] args)throws IOException
 {
  File f=new File("file.txt");
  sop("create:"+f.createNewFile());
  //sop("delete:"+f.delete());
  f.deleteOnExit();
 }
 public static void sop(Object obj)
 {
  System.out.println(obj);
 }
}

3.判断:

boolean exists():文件是否存在。

isFile():是否是文件。

isDirectory():是否是文件夹。

isHidden():是否是隐藏文件。

isAbsolute():是否是绝对路径。

canExecute():是否是可执行文件。

示例2:

import java.io.*;
class FileDemo2
{
 public static void main(String[] args)throws IOException
 {
  method_2();
  method_3();
 }
 public static void sop(Object obj)
 {
  System.out.println(obj);
 }
 public static void method_2()
 {
  File f=new File("file.txt");
  //File f=new File("FileDemo.java");
  sop("execute:"+f.canExecute());
  sop("exists:"+f.exists());
  //创建文件夹。
  File dir=new File("wanglin");
  sop("mkdir:"+dir.mkdir());
  File dir1=new File("wanglin\\tangwei\\abc\\fdree\\java.txt");
  sop("mkdirs:"+dir1.mkdirs());
 }
 public static void method_3()throws IOException
 {
  File f1=new File("file.txt");
  //在判断文件对象是否是文件或者文件夹目录时,必须要先判断该文件对象封装的内容是否存在。通过exists方法判断。
  f1.mkdir();
  sop("dir:"+f1.isDirectory());
  sop("file:"+f1.isFile());
  sop(f1.isAbsolute());
  File f2=new File("d:\\java01\\day20\\file.txt");
  sop(f2.isAbsolute());

 }
}

4.获取:

getName();

getPath():只获取文件对象封装的路径目录。

getParent():获取父目录。

getAbsolutePath():获取绝对路径。

long lastModified():获取文件最后一次修改时间。

long length():获取文件大小。

示例3:

import java.io.*;
class FileDemo3
{
 public static void main(String[] args)throws IOException
 {
  method_4();
  method_5();
 }
 public static void sop(Object obj)
 {
  System.out.println(obj);
 }
 public static void method_4()
 {
  File f=new File("file.txt");
  sop("path:"+f.getPath());
  sop("absolute:"+f.getAbsolutePath());
  //sop("parent:"+f.getParent());
  File f3=new File("wanglin\\file.txt");
  sop("parent:"+f3.getParent());
 }
 public static void method_5()
 {
  File f1=new File("f:\\java01\\day20\\FileDemo.java");
  File f2=new File("d:\\wanglin.txt");
  sop("rename:"+f1.renameTo(f2));
 }
}

 

5.列出文件列表:

list():列出指定目录下所有文件和文件夹名称,包括隐藏文件和文件夹。

示例:

import java.io.*;
class FileDemo4
{
 public static void main(String[] args)
 {
  listRootsDemo();
  listDemo();
 }
 public static void listRootsDemo()
 {
  File[] files=File.listRoots();
  for(File f:files)
  {
   System.out.println(f);
  }
 }
 public static void listDemo()
 {
  File f1=new File("e:\\");
  String[] names=f1.list();
  for(String name:names)
  {
   System.out.println(name);
  }
 }
}

FilenameFilter接口:获取指定目录下的指定名称的文件名。

示例:

import java.io.*;
class FileDemo5
{
 public static void main(String[] args)
 {
  File dir=new File("d:\\");
  File[] files=dir.listFiles();
  for(File f:files)
  {
   System.out.println(f.getName()+"::::"+f.length());
  }
  listDemo_2();
 }
 public static void listDemo_2()
 {
  File dir1=new File("f:\\java01\\day19");
  String[] arr=dir1.list(new FilenameFilter()
  {
   public boolean accept(File dir,String name)
   {
    return name.endsWith(".txt");//获取指定目录下的.txt文件。
   }
  });
  System.out.println("len:"+arr.length);
  for(String name:arr)
  {
   System.out.println(name);
  }
 }
}

 

怎样列出指定目录下的所有内容,包括子内容?

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还有目录的话,还可以再次调用本功能。也就是函数自身调用自身,这种表现形式或者编程手法,称为递归。

递归要注意:

1.限定条件。

2.要注意递归的次数。次数太多,内存会溢出。

递归示例:

import java.io.*;
class FileDemo6
{
 public static void main(String[] args)
 {
  File dir=new File("f:\\java01");
  showDir(dir);
  toBin(74);
  int n=getSum(142);
  System.out.println("n="+n);
 }
 public static int getSum(int n)
 {
  if(n==1)
   return 1;
  return n+getSum(n-1);
 }
 public static void toBin(int num)
 {
  if(num>0)
  {
   toBin(num/2);
   System.out.println(num%2);
  }
 }
 public static void showDir(File dir)
 {
  System.out.println(dir);
  File[] files=dir.listFiles();
  for(File file:files)
  {
   if(file.isDirectory())
    showDir(file);
   else
    System.out.println(file);
  }
 }
}

删除带内容的目录:

删除原理:先删除完里面的内容,再删外面的内容,最后删除指定的文件夹。这时就需要用到递归。

删除文件夹示例:

import java.io.*;
class FileDemo8
{
 public static void main(String[] args)
 {
  File dir=new File("f:\\myclass");
  removeDir(dir);
 }
 public static void removeDir(File dir)
 {
  File[] files=dir.listFiles();
  for(int x=0;x<files.length;x++)
  {
   if(files[x].isDirectory())
    removeDir(files[x]);
   else
    System.out.println(files[x].toString()+":-file-:"+files[x].delete());
  }
  System.out.println(dir+"::dir::"+dir.delete());
 }
}

 

Properties简述

Properties是Hashtable的子类。也就是说它具备Map集合的特点。而且它里面存储的键值对都是字符串。它是集合中和IO技术相结合的集合容器。

Properties对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值

Properties存取元素:

示例:

import java.io.*;
import java.util.*;
class PropertiesDemo
{
 public static void main(String[] args)
 {
  setAndGet();
 }
 public static void setAndGet()
 {
  Properties prop=new Properties();
  prop.setProperty("wanglin01","23");
  prop.setProperty("wanglin02","25");
  prop.setProperty("wanglin03","27");
  System.out.println(prop);
  String value=prop.getProperty("wanglin02");
  System.out.println(value);
  prop.setProperty("wanglin03",20+"");
  Set<String> names=prop.stringPropertyNames();
  for(String s:names)
  {
   System.out.println(s+"::"+prop.getProperty(s));
  }
 }
}

Properties存取配置文件:

示例:

import java.io.*;
import java.util.*;
class PropertiesDemo2
{
 public static void main(String[] args)throws IOException
 {
  //method_1();
  loadDemo();
 }
 public static void loadDemo()throws IOException
 {
  Properties prop=new Properties();
  FileInputStream fis=new FileInputStream("info.txt");
  prop.load(fis);
  System.out.println(prop);
  prop.setProperty("wanglin03",30+"");
  FileOutputStream fos=new FileOutputStream("info.txt");
  prop.store(fos,"tangwei");
  prop.list(System.out);
  fos.close();
  fis.close();
 }
 public static void method_1()throws IOException
 {
  BufferedReader bufr=new BufferedReader(new FileReader("info.txt"));
  String line=null;
  Properties prop=new Properties();
  while((line=bufr.readLine())!=null)
  {
   String[] arr=line.split("=");
   System.out.println(arr[0]+":::"+arr[1]);
   prop.setProperty(arr[0],arr[1]);
  }
  bufr.close();
  System.out.println(prop);
 }
}

 

IO包中的其他类:

1.打印流:PrintWriter与PrintStream    可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类型的数据都原样打印。

字节打印流:PrintStream

构造函数可以接收的参数类型:File对象 file;字符串路径 String;字节输出流 OutputStream

字符打印流:PrintWriter

构造函数可以接收的参数类型:File对象 file;字符串路径 String;字节输出流 OutputStream;字符输出流 Writer

打印流示例:

import java.io.*;
class PrintStreamDemo
{
 public static void main(String[] args)throws IOException
 {
  BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
  //PrintWriter out=new PrintWriter(new FileWriter("a.txt"),true);
  //PrintWriter out=new PrintWriter(System.out);
  PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("a.txt")),true);
  String line=null;
  while((line=bufr.readLine())!=null)
  {
   if("over".equals(line))
    break;
   out.println(line.toUpperCase());
   out.flush();
  }
  out.close();
  bufr.close();
 }
}

 

2.序列流:SequenceInputStream   将多个文件的输入流合并为一个输入流。

示例:

import java.io.*;
import java.util.*;
class SequenceDemo
{
 public static void main(String[] args)throws IOException
 {
  Vector<FileInputStream> v=new Vector<FileInputStream>();
  v.add(new FileInputStream("d:\\1.txt"));
  v.add(new FileInputStream("d:\\2.txt"));
  v.add(new FileInputStream("d:\\3.txt"));
  Enumeration<FileInputStream> en=v.elements();
  SequenceInputStream sis=new SequenceInputStream(en);
  FileOutputStream fos=new FileOutputStream("d:\\4.txt");
  byte[] buf=new byte[1024];
  int len=0;
  while((len=sis.read(buf))!=-1)
  {
   fos.write(buf,0,len);
  }
  fos.close();
  sis.close();
 }
}

切割指定文件,再将切割后的文件碎片合并。

操作示例:

import java.io.*;
import java.util.*;
class SplitFile
{
 public static void main(String[] args)throws IOException
 {
  splitFile();
  //merge();
 }
 public static void merge()throws IOException
 {
  ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
  for(int x=1;x<=4;x++)
  {
   al.add(new FileInputStream("f:\\splitfiles\\"+x+".part"));
  }
  final Iterator<FileInputStream> it=al.iterator();
  Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
  {
   public boolean hasMoreElements()
   {
    return it.hasNext();
   }
   public FileInputStream nextElement()
   {
    return it.next();
   }
  };
  SequenceInputStream sis=new SequenceInputStream(en);
  FileOutputStream fos=new FileOutputStream("f:\\splitfiles\\0.mp3");
  byte[] buf=new byte[1024];
  int len=0;
  while((len=sis.read(buf))!=-1)
  {
   fos.write(buf,0,len);
  }
  fos.close();
  sis.close();
 }
 public static void splitFile()throws IOException
 {
  FileInputStream fis=new FileInputStream("f:\\1.mp3");
  FileOutputStream fos=null;
  byte[] buf=new byte[1024*1024];
  int len=0;
  int count=1;
  while((len=fis.read(buf))!=-1)
  {
   fos=new FileOutputStream("f:\\splitfiles\\"+(count++)+".part");
   fos.write(buf,0,len);
   fos.close();
  }
  fis.close();
 }
}

 

3.操作对象:ObjectInputStream与ObjectOutputStream   被操作的对象需要实现Serializable接口(标记接口)。

对象的序列化:将堆内存中的对象数据保存到硬盘上的一个文件中,从而将对象永久保存,这就叫做对象序列化,也叫对象持久化。

对象序列化示例:

Person对象:

import java.io.*;
class Person implements Serializable
{
 public static final long serialVersionUID=48L;
 private String name;
 transient int age;
 static String country="cn";
 Person(String name,int age,String country)
 {
  this.name=name;
  this.age=age;
  this.country=country;
 }
 public String toString()
 {
  return name+"::"+age+"::"+country;
 }
}
将Person对象序列化:

import java.io.*;
class ObjectStreamDemo
{
 public static void main(String[] args)throws Exception
 {
  writeObj();
  //readObj();
 }
 public static void readObj()throws Exception
 {
  ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.txt"));
  Person p=(Person)ois.readObject();
  System.out.println(p);
  ois.close();
 }
 public static void writeObj()throws IOException
 {
  ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.txt"));
  oos.writeObject(new Person("wanglin01",22,"jp"));
  oos.close();
 }
}

 

4.RandomAccessFile:随机访问文件,自身具备读写的方法。该类不算是IO体系中的子类,而是直接继承自Object类。但是它是IO包中成员,因为它具备读写功能。该类内部封装了一个字节数组,可以通过指针对数组的元素进行操作。可以通过getFilePointer获取指针的位置,再通过seek方法或skipBytes方法改变指针的位置。从而达到随机访问。其实该类完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能操作文件。而且操作的文件有两种模式:r(只读),rw(读写)。

示例:

import java.io.*;
class RandomAccessFileDemo
{
 public static void main(String[] args)throws IOException
 {
  //writeFile();
  writeFile_2();
  readFile();
  RandomAccessFile raf=new RandomAccessFile("ran1.txt","rw");
  //RandomAccessFile raf=new RandomAccessFile("ran1.txt","r");
  raf.write("tang".getBytes());
 }
 public static void readFile()throws IOException
 {
  RandomAccessFile raf=new RandomAccessFile("ran.txt","r");
  raf.seek(8*1);//将指针调整到脚标8位置。
  //raf.skipBytes(8);//跳过8个字节。
  byte[] buf=new byte[4];
  raf.read(buf);
  String name=new String(buf);
  int age=raf.readInt();
  System.out.println("name="+name);
  System.out.println("age="+age);
  raf.close();
 }
 public static void writeFile_2()throws IOException
 {
  RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
  raf.seek(8*0);
  //raf.seek(8*3);
  raf.write("丽丽".getBytes());
  raf.writeInt(201);
  raf.close();
 }
 public static void writeFile()throws IOException
 {
  RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
  raf.write("宝宝".getBytes());
  raf.writeInt(97);
  raf.write("贝贝".getBytes());
  raf.writeInt(99);
  raf.close();
 }
}

5.管道流:PipedInputStream和PipedOutputStream   输入输出可以直接进行连接,通过结合线程使用。涉及到多线程技术的IO流对象。

示例:

import java.io.*;
class Read implements Runnable
{
 private PipedInputStream in;
 Read(PipedInputStream in)
 {
  this.in=in;
 }
 public void run()
 {
  try
  {
   byte[] buf=new byte[1024];
   System.out.println("读取前。。。没有数据阻塞");
   int len=in.read(buf);
   System.out.println("读到数据。。。阻塞结束");
   String s=new String(buf,0,len);
   System.out.println(s);
   in.close();
  }
  catch (IOException e)
  {
   throw new RuntimeException("管道读取流失败");
  }
 }
}
class Write implements Runnable
{
 private PipedOutputStream out;
 Write(PipedOutputStream out)
 {
  this.out=out;
 }
 public void run()
 {
  try
  {
   System.out.println("开始写入数据,等待6秒后");
   Thread.sleep(6000);
   out.write("piped lai la".getBytes());
   out.close();
  }
  catch (Exception e)
  {
   throw new RuntimeException("管道输出流失败");
  }
 }
}
class PipedStreamDemo
{
 public static void main(String[] args)throws IOException
 {
  PipedInputStream in=new PipedInputStream();
  PipedOutputStream out=new PipedOutputStream();
  in.connect(out);
  Read r=new Read(in);
  Write w=new Write(out);
  new Thread(r).start();
  new Thread(w).start();
 }
}

6.操作基本数据类型的数据的流对象:DataInputStream和DataOutputStream

示例:

import java.io.*;
class DataStreamDemo
{
 public static void main(String[] args)throws IOException
 {
  writeData();
  readData();
 }
 public static void writeData()throws IOException
 {
  DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
  dos.writeInt(346);
  dos.writeBoolean(false);
  dos.writeDouble(45893.9823);
  dos.close();
 }
 public static void readData()throws IOException
 {
  DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
  int num=dis.readInt();
  boolean b=dis.readBoolean();
  double d=dis.readDouble();
  sop("num="+num);
  sop("b="+b);
  sop("d="+d);
 }
 public static void sop(Object obj)
 {
  System.out.println(obj);
 }
}

 

7.操作字节数组的流对象:

ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。

ByteArrayOutputStream:在构造的时候,不用定义数据目的。因为该对象中已经封装了可变长度的字节数组,这就是数据目的地。

示例:

import java.io.*;
class ByteArrayStream
{
 public static void main(String[] args)
 {
  ByteArrayInputStream bis=new ByteArrayInputStream("wanglin01".getBytes());
  ByteArrayOutputStream bos=new ByteArrayOutputStream();
  int by=0;
  while((by=bis.read())!=-1)
  {
   bos.write(by);
  }
  System.out.println(bos.size());
  System.out.println(bos.toString());
 }
}

转换流的字符编码:

字符流的出现为了方便操作字符。更重要的是加入了编码转换。通过子类转换流来完成:InputStreamReader和OutputStreamWriter。这两个流对象进行构造的时候可以加入字符集。

编码表的由来:

计算机只能识别二进制数据。为了方便应用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。

常见的编码表:

ASCII:美国标准信息交换码。用一个字节的7位可以表示。

ISO8859-1:欧洲码表。用一个字节的8位表示。

GB2312:中国的中文编码表。

GBK:GB2312的升级版。融合了更多的中文文字符号。

Unicode:国际标准码,融合了多种文字。所有文字都用两个字节表示。Java语言使用的就是Unicode。

UTF-8:国际标准码改进版,最多用三个字节来表示一个字符。

 

转化流的编码应用:

1.可以将字符以指定编码格式存储。

2.可以对文本数据以指定编码格式来读取。

3.指定编码表的动作由构造函数完成。

应用示例:

import java.io.*;
class EncodeStream
{
 public static void main(String[] args)throws IOException
 {
  //writeText();
  readText();
 }
 public static void readText()throws IOException
 {
  //InputStreamReader isr=new InputStreamReader(new FileInputStream("gbk.txt"),"GBK");
  InputStreamReader isr=new InputStreamReader(new FileInputStream("utf.txt"),"GBK");
  char[] buf=new char[10];
  int len=isr.read(buf);
  String str=new String(buf,0,len);
  System.out.println(str);
  isr.close();
 }
 public static void writeText()throws IOException
 {
  //OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");
  OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
  osw.write("你好");
  osw.close();
 }
}

 

字符编码:字符串变成字节数组。通过getBytes(指定的编码表);

字符解码:字节数组变成字符串。通过new String(byte[],指定的编码表);

编码与解码示例:

import java.util.*;
class EncodeDemo
{
 public static void main(String[] args)throws Exception
 {
  String s="你好";
  byte[] b1=s.getBytes("gbk");
  //byte[] b1=s.getBytes("utf-8");
  System.out.println(Arrays.toString(b1));
  //String s1=new String(b1,"GBK");
  //String s1=new String(b1,"UTF-8");
  String s1=new String(b1,"iso8859-1");
  System.out.println("s1="+s1);
  
  byte[] b2=s1.getBytes("ISO8859-1");
  System.out.println(Arrays.toString(b2));
  String s2=new String(b2,"gbk");
  //String s2=new String(b2,"utf-8");
  System.out.println("s2="+s2);
 }
}

 

字符编码中的特殊现象:在记事本程序中写入“联通”两个字,保存后再打开记事本,这两个字变成乱码。原因是:“联通”这两个字的GBK编码的二进制形式正好符合UTF-8的二进制编码规则,记事本程序自动用UTF-8编码表进行解码,所以变成乱码。

 

----------- android培训java培训java学习型技术博客、期待与您交流! ------------


 

 

 

               

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3185次
    • 积分:126
    • 等级:
    • 排名:千里之外
    • 原创:12篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档