18天-06-IO流
  字节流和字符流


  字节流两个基类:
InputStream,FileInputStream,BufferedInputStream
OutputStream,FileOutputStream,BufferedOutputStream
PrintStream (打印字节流,带编码格式)
  字符流两个基类:
Reader,FileReader,BufferedReader,InputStreamReader(字节流转换为字符流读取,带编码格式)
Writer,FileWriter,BufferedWriter,OutputStreamWriter(字节流转换为字符流写入,带编码格式)
PrintWriter (打印字符流,带编码格式)
流操作规律讲解:
源设备:   键盘 System.in;    硬盘 FileStream;      内存 ArrayStream;
目的设备:  控制台 System.out;   硬盘 FileStream;     内存 ArrayStream;

字符流:(只能用于文本文件)
操作FileWriter写入文件:
1.创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该目录下已经有同名文件,将被覆盖。其实该步骤就是在明确数据要存放的目的地。
FileWriter fw=new FileWriter("filePath",true);  //ture代表不覆盖已有文件,并在已有文件末尾添加数据
2.调用write()方法,将字符串写入到流中。
3.刷新流对象中缓冲的数据到文件里。
4.关闭流资源。在关闭流前,会刷新一次内部缓冲区的数据。

操作FileReader读取文件:
1.创建一个文件读取流对象,和指定名称的文件。要保证该文件是已经存在,如果不存在,会发生FileNotFoundException异常。 FileReader fr=new FileReader(FilePath);
2.调用读取流对象的read方法。read();一次读取一个字符,而且会自动往下读取。
第二种通过字符数组进行读取。
定义一个数组,用于存储读取到的字符,读取read(char[])返回的是读取到的字符个数。

复制的原理:其实就是将一个地方的文件数据存储到另外一个指定的地方。

字符流拷贝文件示例:

 /**
* 拷贝文件
*
* @param sourceFile 源文件路径
* @param targetFile 目标文件路径
*/
public static void copyFile(String sourceFile, String targetFile)
{
FileReader fr = null; //读文件
FileWriter fw = null; //写文件
try
{
fr = new FileReader(sourceFile);
fw = new FileWriter(targetFile); char[] temp = new char[];
int length = ;
while ((length = fr.read(temp)) != -)
{
//length是每次读取文件时返回已读取的字符数量,-1为文件读取完毕
fw.write(temp, , length);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (fr != null)
{
fr.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if (fw != null)
{
fw.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

字符流拷贝文件

  缓冲区: BufferedWriter,BufferedReader

  缓冲区的出现是为了提高流的操作效率。所以在创建缓冲区之前,必须要先有流对象。
1.创建流对象(FileReader,FileWriter);
2.将需要提高效率的流对象作为参数传递给缓冲区的构造函数即可;
3.读写数据,并即时刷新缓冲区数据;
4.关闭缓冲区,流对象,缓冲区关闭时会检测一下数据是否写完,所以要后关闭流对象。

字符读取流缓冲区:该缓冲区提供了一个一次读一行的方法readLine(),当返回null时,表示读取到文件末尾。
readLine方法返回的时候只返回回车符之前的数据内容,并不返回包含回车符。
readLine原理:无论是读一行还是读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是read()方法一次读一个。
缓冲区提供了一个跨平台的换行符:newLine();

缓冲区拷贝文件示例:

 /**
* 缓冲区拷贝文件
*
* @param sourceFile 源文件路径
* @param targetFile 目标文件路径
*/
public static void copeFileByBuffer(String sourceFile, String targetFile)
{
BufferedReader bufr = null;
BufferedWriter bufw = null;
try
{
bufr = new BufferedReader(new FileReader(sourceFile));
bufw = new BufferedWriter(new FileWriter(targetFile));
String temp = null;
while ((temp = bufr.readLine()) != null)
{
bufw.write(temp);
bufw.newLine();
bufw.flush();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (bufr != null)
{
bufr.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if (bufw != null)
{
bufw.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

缓冲区拷贝文件

  装饰设计模式:当想要对已有的对象进行功能增强时,可以定义类将已有对象传入,基于已有的功能,并提供增强功能。那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
装饰类因为增强了已有的对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常是都属于一个体系中的。
装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。

  字节流:
int read():读取时返回int类型,会把byte字节提升为int类型,提升方式是byte&0xff,在写入时也做了反向操作强转为byte类型。防止类型提升导致原本不是 -1 的数据在类型提升后变成 -1。

字节流复制文件示例:

 /**
* 字节流方式拷贝文件
*
* @param sourceFile 源文件路径
* @param targetFile 目标文件路径
*/
public static void copyFileByByte(String sourceFile, String targetFile)
{
BufferedInputStream bfis = null;
BufferedOutputStream bfos = null;
try
{
bfis = new BufferedInputStream(new FileInputStream(sourceFile));
bfos = new BufferedOutputStream(new FileOutputStream(targetFile));
byte[] temp = new byte[*];
int length;
while ((length = bfis.read(temp)) != -)
{
bfos.write(temp, , length);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (bfis != null)
{
bfis.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if (bfos != null)
{
bfos.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

字节流方式拷贝文件

  19天-15-IO流读取键盘录入

System.out:  对应的是标准输出设备,控制台。
System.in:    对应的标准输入设备,键盘。

流操作键盘录入示例:

 /**
* 键盘录入,over表示结束
*/
public static void keyboardEntry() throws IOException
{
BufferedReader br = null;
BufferedWriter bw = null;
try
{
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String temp;
while ((temp = br.readLine()) != null)
{
if ("over".equals(temp))
{
break;
}
bw.write(temp);
bw.newLine();
bw.flush();
}
}
finally
{
if (br != null)
{
br.close();
}
if (bw != null)
{
bw.close();
}
}
}

流操作键盘录入

  流操作的基本规律:

通过三方面来确定:
1.明确源和目的
源:输入流,InputStream,Reader
目的:输出流,OutputStream,Writer
2.操作的数据是否是纯文本
是:字符流 否:字节流
3.当体系明确后,再明确要使用哪个具体的对象。
通过设备来区分:源设备:内存,硬盘,键盘;目的设备:内存,硬盘,控制台

  注:转换流:主要用于字节流与字符流的转换和在涉及字符编码时指定编码。

  20天-01-IO流File类
File类:用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作,File对象可以作为参数传递给流的构造函数。
File类常用方法:
1.创建 boolean createNewFile();//在指定位置创建文件,如果该文件已经存在,则不创建文件返回false
      boolean mkdir();//创建文件夹   boolean mkdirs();//创建多级文件夹
2.删除 boolean delete();//删除失败返回false     void deleteOnExit();//在程序退出时删除指定文件
3.判断 exists();//文件是否存在      isHidden();//判断是否是隐藏文件    canExecute();//判断文件是否可执行
    isFile();//是否是文件   isDirectory();//判断是否是目录       isAbsolute();//判断是否是绝对路径
  注:在判断文件对象是否是文件或者目录时,必须要先判断文件对象封装的内容是否存在,通过exists()判断
4.获取 getName();//获取文件名     getPath();//获取文件封装路径    getParent();//获取文件封装父目录
    getAbsolutePath();//获取文件绝对路径   lastModified();//获取文件最后修改时间    length();//获取文件大小

删除文件操作示例:

 /**
* 递归遍历删除所有文件
*
* @param file 文件路径
*/
public static void deleteFile(File file)
{
if (!file.exists())
{
return;
}
File[] fileList = file.listFiles();
for (File f : fileList)
{
if (f.isDirectory())
{
deleteFile(f);
}
else
{
f.delete();
}
}
file.delete();
}

递归遍历删除所有文件

  20天-11-IO流Properties类

  Properties是hashtable的子类,也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串,是集合和IO技术相结合的集合容器。在加载数据时,需要数据有固定的格式:键=值

  打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印。
  字节流打印流:PrintStream 构造函数可以接收的参数类型:
1.file对象,File;2.字符串路径,String;3.字节输出流,OutputStream

  字符打印流:PrintWriter 构造函数可以接收的参数类型:
1.file对象,File;2.字符串路径,String;3.字节输出流,OutputStream;4.字符输出流,Writer

序列流SequenceInputStream:将多个数据源的文件流合并到一起。
文件合并流示例:

 /**
* 把多个文件里面的数据合并到一个文件里面
*
* @param targetFile 合入文件
* @param sourceFiles 多个原文件
* @throws IOException
*/
public static void combineTFiles(String targetFile, String... sourceFiles)
throws IOException
{
ArrayList<FileInputStream> v = new ArrayList<FileInputStream>();
for (String s : sourceFiles)
{
v.add(new FileInputStream(s));
}
Iterator<FileInputStream> it = v.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
@Override
public boolean hasMoreElements()
{
return it.hasNext();
} @Override
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(targetFile);
byte[] bf = new byte[];
int length = ;
while ((length = sis.read(bf)) != -)
{
fos.write(bf, , length);
}
sis.close();
fos.close();
}

文件合并

  对象流ObjectInputStream,ObjectOutputStream:被操作的对象需要实现Serializable(标记接口),对象中的transient和static修饰的成员变量不会被读取和写入

实现Serializable接口的类,需要做一个标记方便后期修改 static final long serialVersionUID = 10L;

  管道流PipedInputStream,PipedOutputStream:输入输出可以直接进行连接,通过结合多线程使用,先把数据写入管道再从管道里面读取出来。
管道流示例:

 class Demo
{
public static void main(String[] args)
{
//exit为退出管道示例命令
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
//读取管道流连接写入管道流,当有数据写入管道时,读取管道线程自动读入数据
pis.connect(pos);
new Thread(new ReadPiped(pis)).start();
new Thread(new WritePiped(pos, System.in)).start();
}
}
class ReadPiped implements Runnable
{
private PipedInputStream in;
public ReadPiped(PipedInputStream in)
{
this.in = in;
}
@Override
public void run()
{
try
{
byte[] bt = new byte[];
int len = ;
while (true)
{
len = in.read(bt);
String str = new String(bt, , len);
if ("exit".equals(str))
{
break;
}
System.out.println(str);
}
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
class WritePiped implements Runnable
{
private PipedOutputStream out;
private BufferedReader bf = null;
public WritePiped(PipedOutputStream out, InputStream in)
{
this.out = out;
bf = new BufferedReader(new InputStreamReader(in));
}
@Override
public void run()
{
try
{
String temp;
while (true)
{
temp = bf.readLine();
out.write(temp.getBytes());
if ("exit".equals(temp))
{
break;
}
}
bf.close();
out.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

键盘录入管道流

  随机访问文件RandomAccessFile:该类不算IO体系中的子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能,内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,同时也可以通过seek修改指针的位置。其实内部完成读写的原理是内部封装了字节输入流和输出流。

  如果模式为只读 r,不会创建文件,会去读取一个已存在的文件,如果文件不存在,则会抛异常。
  如果模式为读写 rw,操作的文件不存在,会自动创建,如果文件存在则不会覆盖。
  特点:可以随机的读写文件里面的数据,用于多线程把数据分段存到一个文件里(多线程下载)。
  void seek(long pos);  //设置指针位置,方便修改指定位置数据
  int skipBytes(int n);  //指针向前跳n个字节,不能向后跳

  基本数据类型流DataInputStream,DataOutputStream:可以用于操作基本数据类型的数据的流对象

  字节数组流
ByteArrayInputStrean:在构造函数里,需要接收数据源,而且数据源是一个字节数组
ByteArrayOutputStream:在构造函数里,不用定义数据目的,该对象内部已经封装了可变长度的字节数组,就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源。所以不用进行close关闭。
void writeTo(OutputStream out);  //把数组里面的数据写入流里面
  字符数组流   CharArrayReader,CharArrayWriter
  字符串流    StringReader,StringWriter

  21天-07-字符编码
ASCII:美国标准信息交换码,用一个字节的7位可以表示
ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字字符,用两个字节的8位表示,每个字节前面第一位是标识
Unicode:国际标准码,融合了多种文字,所有文字都用两个字节来表示,Java语言使用的就是Unicode
UTF-8:最多用三个字节来表示一个字符

编码:字符串变成字节数组
String-->byte[];   str.getBytes(charsetName);
解码:字节数组变成字符串
byte[]-->String;   new String(byte[],charsetName);
编码转换示例:

 import java.io.IOException;
import java.io.UnsupportedEncodingException;
class Demo
{
public static void main(String[] args)throws IOException
{
encodeShow("test", "gbk");
encodeShow("test", "utf-8");
encodeShow("test", "GB2312");
encodeShow("test", "ascii");
encodeShow("test", "unicode");
encodeShow("test", "ISO8859-1");
}
public static void encodeShow(String param, String charset)
throws UnsupportedEncodingException
{
String str = param;
sop("source string: " + str + " encode is: " + charset);
byte[] bt = str.getBytes(charset);
for (byte b : bt)
{
sop("encode binary: " + Integer.toBinaryString(b));
}
String t = new String(bt, charset);
sop("encode string: " + t);
sop("");
}
private static void sop(Object obj)
{
System.out.println(obj);
}
}

编码转换

换行符: Linux:\n    windows:\r\n    Mac:\r

Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)的更多相关文章

  1. Java基础知识_毕向东_Java基础视频教程笔记(22-25 GUI 网络编程 正则)

    22天-01-GUIGUI:Graphical User Interface 图形用户接口 Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中CLI:Common lin ...

  2. Java基础知识_毕向东_Java基础视频教程笔记(26 反射)

    Java反射机制: 是在运行状态中,对于任意一个类(class)文件,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性.这种动态获取的信息以及动态调用对象的方法的功 ...

  3. Java基础知识_毕向东_Java基础视频教程笔记(14-18集合框架)

    14天-01-集合框架集合类出现:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式.数组与集合类同是容器,有何不同? 数组长度 ...

  4. Java基础知识_毕向东_Java基础视频教程笔记(11-12 多线程)

    11天-01-多线程进程:是一个正在执行中的程序.每个进程执行都有一个执行顺序.该顺序是一个执行路径或者叫一个控制单元.线程:是进程中的一个独立的控制单元,线程在控制着进程的执行.一个进程至少有一个线 ...

  5. Java基础知识_毕向东_Java基础视频教程笔记(5-10 面向对象)

    06天-05-面向对象(帮助文档的制作javadoc):java文档生成命令:javadoc -d filepatn demo.java   -author -version(可选)一个类中默认会有一 ...

  6. Java基础知识_毕向东_Java基础视频教程笔记(13 字符)

    13天-01-String String类适用于描述字符串事物. 常见的操作:1.获取: 1.1字符串中包含的字符数,也就是字符串的长度. int length():获取长度 1.2根据索引值获取位置 ...

  7. 黑马程序员_毕向东_Java基础视频教程——java语言组成部分(随笔)

    java语言组成部分 Java是一种强类型语言,所谓强类型语言就是对具体的数据进行不同的定义.对类型的划分的十分细致,对内存中分配了不同大小的内u你空间 关键字 标识符 注释 变量和常量 运算符 语句 ...

  8. 黑马程序员_毕向东_Java基础视频教程——算术运算符小点(随笔)

    算术运算符小点 ​ 取模 class Test{ public static void main(String[] args){ System.out.println( 1 % -5); System ...

  9. 黑马程序员_毕向东_Java基础视频教程——变量(随笔)

    变量 变量 就是将不确定的数据进行存储.也就是需要在内存中开辟一块空间. 内存就是一块运算区域.内存越大.内存中装的数位就越多.运算就越快 ============================== ...

随机推荐

  1. debezium sql server 集成

    debezium 是一个方便的cdc connector 可以帮助我们解决好多数据实时变更处理.数据分析.微服务的数据通信 从上次跑简单demo到现在,这个工具是有好多的变更,添加了好多方便的功能,支 ...

  2. Physics for Game Programmers (Grant Palmer 著)

    CHAPTER1 Adding Realism to Your Games CHAPTER2 Some Basic Concepts CHAPTER3 Basic Newtonian Mechanic ...

  3. BinaryReader 自己写序列化

    听说过BinaryReader和BinaryWriter吗? 序列化无非就是网络通信时所使用的传输数据的方式,而BinaryWriter可以将数据以二进制的方式写入到流当中.比如Int32型的1用Bi ...

  4. setsockopt调用IP_ADD_MEMBERSHIP出错errno:19 no such device

    if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {                 pri ...

  5. SelectDataTable

    项目地址 :  https://github.com/kelin-xycs/SelectDataTable SelectDataTable 一个 用 C# 实现的 用 Sql select DataT ...

  6. ZeroTier One

    ZeroTier – 无配置,零基础「内网穿透」随时随地连回家/学校/办公室 [跨平台] https://www.appinn.com/zerotier-one/ Virtual NetworkZer ...

  7. python多线程、多进程相关知识

    Queue Queue用于建立和操作队列,常和threading类一起用来建立一个简单的线程队列. 首先,队列有很多种,根据进出顺序来分类,可以分成 Queue.Queue(maxsize) FIFO ...

  8. vim使用技巧大全

    1.vim清空内容 光标移到第一行,然后在非插入模式按10000后然后点dd .要嫌笨的话就在非插入模式下输入:.,$d 一回车就全没了 2.vim光标跳转操作 1.跳到文本的最后一行:按“G”,即“ ...

  9. Oracle 增加、修改、删除字段

    分别对T_USER表 进行增加name字段, 修改name字段,删除name字段 /*增加列表*/ ALTER TABLE T_USERS ADD name varchar2(512) ; /*删除列 ...

  10. ASP.NET AJAX入门系列(9):在母版页中使用UpdatePanel

    本文简单介绍一下在母版页中使用UpdatePanel控件,翻译自官方文档. 主要内容 1.添加UpdatePanel控件到Content Page 2.通过Master Page刷新UpdatePan ...