天天看点

java知识点拾遗(IO流-1)

  1. 主要类
  2. java知识点拾遗(IO流-1)
  3. File类
  • 名称分隔符
path1="d:/temp/test.txt";
path2="d:"+File.separator+"temp"+File.separator+"test.txt";

//1、构建File对象
File src = new File(path);
System.out.println(src.length());

//2、构建File对象
src = new File("D:/java300/IO_study01","IO.png");
src = new File("D:/java300/","IO_study01/IO.png");
System.out.println(src.length());

//3、构建File对象
src = new File(new File("D:/java300/IO_study01"),"IO.png");
System.out.println(src.length());      
  • 路径基本信息
//用户目录
System.out.println(System.getProperty("user.dir"));
//取得绝对路径
src = new File("IO.png");
System.out.println(src.getAbsolutePath());

File src = new File("IO_study01/IO.png");
    
//基本信息
System.out.println("名称:"+src.getName());
System.out.println("路径:"+src.getPath());
System.out.println("绝对路径:"+src.getAbsolutePath());
System.out.println("父路径:"+src.getParent());
System.out.println("父对象:"+src.getParentFile().getName());

//文件状态
src = new File("xxx");
if(null == src || !src.exists()) {
  System.out.println("文件不存在");
}else {
  if(src.isFile()) {
    System.out.println("文件操作");
  }else { //src.isDirectory()
    System.out.println("文件夹操作");
  }
}

//获取文件的长度字节数(文件夹返回0)
File src = new File("D:/java300/IO_study01/IO.png");
System.out.println("长度:"+ src.length());

//文件操作
//createNewFile()  : 不存在才创建,存在创建失败,只能创建文件
//delete():删除已经存在的文件
//操作系统的设备名不能作为文件名创建
File src = new File("D:/java300/IO_study01/io.txt");
boolean flag =src.createNewFile();
System.out.println(flag);
flag = src.delete();
System.out.println(flag);      
  • 创建目录
//1、mkdir() : 确保上级目录存在,不存在创建失败
//2、mkdirs(): 上级目录可以不存在,不存在一同来创建

File dir = new File("D:/java300/IO_study01/dir/test");
//创建目录 mkdirs()
boolean flag = dir.mkdirs();
System.out.println(flag);
//创建目录 mkdir()
dir = new File("D:/java300/IO_study01/dir/test2");
flag = dir.mkdirs();
System.out.println(flag);      
  • 列出目录信息
File dir = new File("D:/java300/IO_study01");
    
//下级名称  list
String[] subNames = dir.list();
for(String s:subNames) {
  System.out.println(s);
}

//下级对象  listFiles()
File[] subFiles = dir.listFiles();
for(File s:subFiles) {
  System.out.println(s.getAbsolutePath());
}

//所有盘符
File[] roots = dir.listRoots();
for(File r:roots) {
  System.out.println(r.getAbsolutePath());
}      
  • 统计目录的大小(Byte)
public class Test {
  public static void main(String[] args) {
    File src =  new File("D:\\java300\\IO_study01");
    count(src);
    System.out.println(len);
  }
  private static long len =0;
  public static void count(File src) {  
    //获取大小
    if(null!=src && src.exists()) {
      if(src.isFile()) {  //大小
        len+=src.length();
      }else { //子孙级
        for(File s:src.listFiles()) {
            count(s);
        }
      }
    }
  }
}      
  1. 字符编码

    Java字符使用16位的双字节存储。

字符集 说明
US-ASCII ASCII编码
ISO-8859-1 Latin-1 拉丁字符,包含中文,日文等
UTF-8 变长Unicode字符(1-3字节),英文字符占1个字节,中文字符占3个字节。
UTF-16BE 定长Unicode字符(2字节),Gig-Ending编码:高字节低地址
UTF-16LE 定长Unicode字符(2字节),Little-Ending编码:低字节低地址
UTF_16 文件的开头指明BE/LE编码方式,即BOM(Byte Order Mark):“FE FF”表示BE编码,“FF FE”表示LE编码

这里ANSI指系统默认的字符集——windows中文环境下默认字符集是GBK。

  • 字符编码
String english = "abc";
String chinese = "将进酒";

byte[] data1 = english.getBytes();
System.out.println("英文\"" + english + "\"的长度:" + data1.length);
byte[] data2 = english.getBytes("GBK");
System.out.println("英文\"" + english + "\"的长度:" + data2.length);

byte[] data3 = chinese.getBytes(); // 默认getBytes("UTF8"),工程字符集,字符集名称大小写均可
System.out.println("中文\"" + chinese + "\"的长度:" + data3.length);
byte[] data4 = chinese.getBytes("GBK");
System.out.println("中文\"" + chinese + "\"的长度:" + data4.length);      
  • 字符解码

    String–>byte[]:编码

    byte[] -->String:解码

String str1 = "米国USA";
byte[] data = str1.getBytes();

String str2 = new String(data, 0, data.length, "gbk");
System.out.println(str2);
String str3 = new String(data, "utf8");
System.out.println(str3);      
  • 乱码的原因
  • 字节数不够
  • 编码字符集不匹配
  • 中文字符集

    cp936<gb2312<bgk

  1. IO流
  2. java知识点拾遗(IO流-1)
  • 字节流

    InputStream/OutputStream

  • 字符流

    Reader/Writer

  • 读操作步骤(概念)
//1、创建源
File src = new File("abc.txt");
//2、选择流
try {
  InputStream  is =new FileInputStream(src);
  //3、操作 (读取)
  int data1 = is.read(); //第一个数据s
  int data2  = is.read(); //第二个数据x
  int data3  = is.read(); //第三个数据t
  int data4  = is.read(); //????不是数据,文件的末尾返回-1
  System.out.println((char)data1);
  System.out.println((char)data2);
  System.out.println((char)data3);
  System.out.println(data4);
  //4、释放资源
  is.close();
} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}      
  • 操作步骤

字节读

//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream  is =null;
try {
  is =new FileInputStream(src);
  //3、操作 (读取)
  int temp ;
  while((temp=is.read())!=-1) { //一个字节一个字节地读
    System.out.println((char)temp);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、释放资源
  try {
    if(null!=is) {
      is.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      

块读

//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream  is =null;
try {
  is =new FileInputStream(src);
  //3、操作 (分段读取)
  byte[] flush = new byte[1024*10]; //缓冲容器
  int len = -1; //接收长度
  while((len=is.read(flush))!=-1) {
    //字节数组-->字符串 (解码)
    String str = new String(flush,0,len); //String str = new String(flush, "utf8");
    System.out.print(str);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、释放资源
  try {
    if(null!=is) {
      is.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      
  • 写操作
//1、创建源
File dest = new File("dest.txt");
//2、选择流
OutputStream os =null;
try {
  os = new FileOutputStream(dest,true); //true表示追加写入
  //3、操作(写出)
  String msg ="IO is so easy\r\n";
  byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码,默认字符集)
  //byte[] datas  = msg.getBytes("utf8"); 按照utf8字符集编码
  os.write(datas,0,datas.length); //或者out.write(datas);
  os.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、释放资源
  try {
    if (null != os) {
      os.close();
    } 
  } catch (Exception e) {
  }
}      
  • 释放资源

    先打开的后关闭,后打开的先关闭。

    可以利用Closeable接口封装释放资源的动作。

public static void close(Closeable... ios) {
  for(Closeable io:ios) {
    try {
      if(null!=io) {
        io.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}      

或者可以利用try …with…resources自动资源释放(JDK7之后)

try(is;os) { //<----------is和os自动释放     
或者
try( InputStream is=new FileInputStream(src);
     OutputStream os=new FileOutputStream(dest);){
     
  ......
  ......
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}      
  • 纯文本处理

    FileReader/FileWriter(内置解决字符编解码问题)

    append()返回Writer,故可以实现链式引用。

块读

//1、创建源
File src = new File("abc.txt");
//2、选择流
Reader  reader =null;
try {
  reader =new FileReader(src);
  //3、操作 (分段读取)
  char[] flush = new char[1024]; //缓冲容器,注意是字符数组不是字节数组
  int len = -1; //接收长度
  while((len=reader.read(flush))!=-1) {
    //字符数组-->字符串,解码无需指定字符集(系统已经处理好了)
    String str = new String(flush,0,len);
    System.out.println(str);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、释放资源
  try {
    if(null!=reader) {
      reader.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      

块写

//1、创建源
File dest = new File("dest.txt");
//2、选择流
Writer writer =null;
try {
  writer = new FileWriter(dest);
  //3、操作(写出)
  //写法一
  //String msg ="I love you baby\r\n你知道我在等你吗";
  //char[] datas =msg.toCharArray(); // 字符串-->字符数组(不存在编码问题)
  //writer.write(datas,0,datas.length);
  写法二
  String msg ="I love you baby\r\n你知道我在等你吗";
  writer.write(msg);  
  writer.write("add");    
  writer.flush();
  
  //写法三
  //writer.append("I love you baby\r\n").append("你知道我在等你吗");
  //writer.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、释放资源
  try {
    if (null != writer) {
      writer.close();
    } 
  } catch (Exception e) {
  }
}      
  • 字节数组流

    ByteArrayInputStream&ByteArrayOutputStream,在内存中,Java可以直接访问,无需关闭。

  • 处理流

    使用了装饰模式。

  • java知识点拾遗(IO流-1)
  • 装饰器类包裹/包装基本类。接口方法(产生多态行为)从装饰器类向基本类方向层层调用,然后由内层的基本类向外部的包装类层层返回。抽象类实现接口,但主要是要提供公共属性。
  1. 流的缓冲
  • 提供缓冲的装饰流类可以提高IO性能。
  • 控制流的基础是节点流,底层不能没有节点流。
  • 释放外层装饰器流类的对象,则内层的基本流类对象资源会自动释放。释放是从里到外依次释放。

这里节点流是基本IO流类,而控制流是装饰器IO流类。装饰器IO流类提供流的缓冲提升IO效能。控制流类包装节点流类——装饰器类包装基本类。

示例如下:

File src = new File("abc.txt");
...
is=new BufferedInputStream(new FileInputStream(src));
          装饰器类                   基本类
          控制流类                   节点流类
          提升IO效能
          后释放(手动)             先释放(自动)
-------------------------------------------------------------------
File dest = new File("dest.txt");
...
os =new BufferedOutputStream( new FileOutputStream(dest));      
  1. 字符输入输出加入缓冲流
  • 读入
//1、创建源
File src = new File("abc.txt");
//2、选择流
BufferedReader  reader =null;
try {
  reader =new BufferedReader(new FileReader(src));
  //3、操作 (分段读取)
  String line =null;
  while((line=reader.readLine())!=null) {
    //字符数组-->字符串
    System.out.println(line);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、释放资源
  try {
    if(null!=reader) {
      reader.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      
  • 写出
//1、创建源
File dest = new File("dest.txt");
//2、选择流
BufferedWriter writer =null;
try {
  writer = new BufferedWriter(new FileWriter(dest));
  //3、操作(写出)      
  writer.append("I love you baby");
  writer.newLine(); //输出一个\r\n
  writer.append("偏偏喜欢你");
  writer.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、释放资源
  try {
    if (null != writer) {
      writer.close();
    } 
  } catch (Exception e) {
  }
}      
  1. 转换流

    CharactorStreams—>InputStreamReader/OutputStreamWriter—>ByteStreams

  • 将字节流转换成字符流
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
  //循环获取键盘的输入(exit退出),输出此内容
  String msg ="";
  while(!msg.equals("exit")) {
    msg = reader.readLine(); //循环读取
    writer.write(msg); //循环写出
    writer.newLine();
    writer.flush(); //强制刷新。不强制刷新,在缓存未满时不输出,卡在上一步。
  }
}catch(IOException e) {
  System.out.println("操作异常");
}      
  • 处理指定字符集
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;

public class ConvertTest {
  public static void main(String[] args) {
    try(BufferedReader reader =
        new BufferedReader(
            new InputStreamReader(
                new URL("http://www.baidu.com").openStream(),"UTF-8"));
      BufferedWriter writer =
        new BufferedWriter(
          new OutputStreamWriter(
            new FileOutputStream("baidu.html"),"UTF-8"));){
      //3、操作 (读取)
      String msg ;
      while((msg=reader.readLine())!=null) {
        //System.out.println(msg);
        writer.write(msg); //如果字符集不统一将出现乱码
        writer.newLine();
      }          
      writer.flush();
    }catch(IOException e) {
      System.out.println("操作异常");
    }  
  }
}      
  1. 数据流

    DataInputStream/DataOutputStream保存了数据及其类型。

//写出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作数据类型 + 数据
dos.writeUTF("白日依山尽");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//读取
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dis.readUTF(); 
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);