Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)
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流)的更多相关文章
- Java基础知识_毕向东_Java基础视频教程笔记(22-25 GUI 网络编程 正则)
22天-01-GUIGUI:Graphical User Interface 图形用户接口 Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中CLI:Common lin ...
- Java基础知识_毕向东_Java基础视频教程笔记(26 反射)
Java反射机制: 是在运行状态中,对于任意一个类(class)文件,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性.这种动态获取的信息以及动态调用对象的方法的功 ...
- Java基础知识_毕向东_Java基础视频教程笔记(14-18集合框架)
14天-01-集合框架集合类出现:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式.数组与集合类同是容器,有何不同? 数组长度 ...
- Java基础知识_毕向东_Java基础视频教程笔记(11-12 多线程)
11天-01-多线程进程:是一个正在执行中的程序.每个进程执行都有一个执行顺序.该顺序是一个执行路径或者叫一个控制单元.线程:是进程中的一个独立的控制单元,线程在控制着进程的执行.一个进程至少有一个线 ...
- Java基础知识_毕向东_Java基础视频教程笔记(5-10 面向对象)
06天-05-面向对象(帮助文档的制作javadoc):java文档生成命令:javadoc -d filepatn demo.java -author -version(可选)一个类中默认会有一 ...
- Java基础知识_毕向东_Java基础视频教程笔记(13 字符)
13天-01-String String类适用于描述字符串事物. 常见的操作:1.获取: 1.1字符串中包含的字符数,也就是字符串的长度. int length():获取长度 1.2根据索引值获取位置 ...
- 黑马程序员_毕向东_Java基础视频教程——java语言组成部分(随笔)
java语言组成部分 Java是一种强类型语言,所谓强类型语言就是对具体的数据进行不同的定义.对类型的划分的十分细致,对内存中分配了不同大小的内u你空间 关键字 标识符 注释 变量和常量 运算符 语句 ...
- 黑马程序员_毕向东_Java基础视频教程——算术运算符小点(随笔)
算术运算符小点 取模 class Test{ public static void main(String[] args){ System.out.println( 1 % -5); System ...
- 黑马程序员_毕向东_Java基础视频教程——变量(随笔)
变量 变量 就是将不确定的数据进行存储.也就是需要在内存中开辟一块空间. 内存就是一块运算区域.内存越大.内存中装的数位就越多.运算就越快 ============================== ...
随机推荐
- debezium sql server 集成
debezium 是一个方便的cdc connector 可以帮助我们解决好多数据实时变更处理.数据分析.微服务的数据通信 从上次跑简单demo到现在,这个工具是有好多的变更,添加了好多方便的功能,支 ...
- Physics for Game Programmers (Grant Palmer 著)
CHAPTER1 Adding Realism to Your Games CHAPTER2 Some Basic Concepts CHAPTER3 Basic Newtonian Mechanic ...
- BinaryReader 自己写序列化
听说过BinaryReader和BinaryWriter吗? 序列化无非就是网络通信时所使用的传输数据的方式,而BinaryWriter可以将数据以二进制的方式写入到流当中.比如Int32型的1用Bi ...
- setsockopt调用IP_ADD_MEMBERSHIP出错errno:19 no such device
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) { pri ...
- SelectDataTable
项目地址 : https://github.com/kelin-xycs/SelectDataTable SelectDataTable 一个 用 C# 实现的 用 Sql select DataT ...
- ZeroTier One
ZeroTier – 无配置,零基础「内网穿透」随时随地连回家/学校/办公室 [跨平台] https://www.appinn.com/zerotier-one/ Virtual NetworkZer ...
- python多线程、多进程相关知识
Queue Queue用于建立和操作队列,常和threading类一起用来建立一个简单的线程队列. 首先,队列有很多种,根据进出顺序来分类,可以分成 Queue.Queue(maxsize) FIFO ...
- vim使用技巧大全
1.vim清空内容 光标移到第一行,然后在非插入模式按10000后然后点dd .要嫌笨的话就在非插入模式下输入:.,$d 一回车就全没了 2.vim光标跳转操作 1.跳到文本的最后一行:按“G”,即“ ...
- Oracle 增加、修改、删除字段
分别对T_USER表 进行增加name字段, 修改name字段,删除name字段 /*增加列表*/ ALTER TABLE T_USERS ADD name varchar2(512) ; /*删除列 ...
- ASP.NET AJAX入门系列(9):在母版页中使用UpdatePanel
本文简单介绍一下在母版页中使用UpdatePanel控件,翻译自官方文档. 主要内容 1.添加UpdatePanel控件到Content Page 2.通过Master Page刷新UpdatePan ...