------- android培训、java培训、期待与您交流! ----------
IO流:用于处理设备之间的数据传输
按操作数据分为:字节流和字符流流
按流向分为:输入流,输出流
输入:将外设中的数据读取到内存中
输出:将内存的数据写入到外设中
缓冲的原理:从源中获取一批数据装进缓冲区中,再从缓冲区中不断取出一个个数据,取完后再从源中继续取一批数据进缓冲区。当源中数据取完,用-1作结束。
思路:缓冲区就是封装了一个数组,并对外提供了更多的方法对数组进行访问,其实这些方法最终操作的都是数组的角标
IO流一般使用原则:
一、按数据来源(去向)分类:
2、是byte[]:ByteArrayInputStream, ByteArrayOutputStream
3、是Char[]: CharArrayReader, CharArrayWriter
4、是String: StringBufferInputStream, StringReader, StringWriter
5、网络数据流:InputStream, OutputStream, Reader, Writer
二、按是否格式化输出分:
要格式化输出:PrintStream, PrintWriter
三、按是否要缓冲分:
要缓冲:BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
四、按数据格式分:
1、二进制格式(只要不能确定是纯文本的): InputStream, OutputStream及其所有带Stream结束的子类
2、纯文本格式(含纯英文与汉字或其他编码方式);Reader, Writer及其所有带Reader, Writer的子类
五、按输入输出分:
1、输入:Reader, InputStream类型的子类
2、输出:Writer, OutputStream类型的子类
六、特殊需要:
1、从Stream到Reader,Writer的转换类:InputStreamReader, OutputStreamWriter
2、对象输入输出:ObjectInputStream, ObjectOutputStream
3、进程间通信:PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
4、合并输入:SequenceInputStream
5、更特殊的需要:PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
File类常见方法:
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息。
getName():
getPath():
getParent():
getAbsolutePath()
long lastModified()
long length()
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-size:12px;">/*
* 创建一个可以往文件写入字符数据的字符输出对象。
* 同时明确该文件(用于存储数据目的地)
* 如果文件不存在,会自动创建,否则会被覆盖
*/
public class FileWriterDemo {
private static final String LINE_SEPARATOR = System
.getProperty("line.separator");
public static void main(String[] args) throws IOException {
// 构造函数加入"true",可以实现对文件续写
FileWriter fw = new FileWriter("demo.txt", true);
// write方法写入数据到临时存储缓冲区
fw.write("abcds" + LINE_SEPARATOR + "HAAE");
// fw.flush();//刷新数据到目的地
// 关闭流。关闭前会先调用flush方法。
fw.close();
}
}</span></span></span></span></span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-size:12px;">public class FileReaderDemo {
public static void main(String[] args) {
FileReader fr = null;
try {
fr = new FileReader("demo.txt");
char[] buf = new char[1024];
int len = 0;
while ((len = fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
} catch (IOException e) {
System.out.println("读取异常" + e.toString());
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e1) {
System.out.println("关闭异常" + e1.toString());
}
}
}
}
}</span></span></span></span></span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class MyBufferedReader extends Reader {
private Reader r;
private char[] buf = new char[1024];
private int pos = 0;
private int count = 0;
MyBufferedReader(Reader r) {
this.r = r;
}
/*
* //1,从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。 if(count==0){ count =
* r.read(buf); if(count<0) return -1; 每次获取数据到缓冲区后,角标归零. pos = 0; char ch =
* buf[pos];
*/
public int myRead() throws IOException {
if (count == 0) {
count = r.read(buf);
pos = 0;
}
if (count < 0)
return -1;
char ch = buf[pos++];
count--;
return ch;
}
public String myReadLine() throws IOException {
// 定义一个StringBuilder容器,最终还要将数据转为字符串
StringBuilder sb = new StringBuilder();
int ch = 0;
while ((ch = r.read()) != -1) {
// 因为Window下每一行回车的字符是'\r\n',要作判断
if (ch == '\r')
continue;
// 如果是回车符,说明行结束,返回字符串
if (ch == '\n')
return sb.toString();
// 行未结束,则继续添加字符
else
sb.append((char) ch);
}
// 防止最后一行遗漏,判断sb不为空则返回最后一行数据
if (sb.length() != 0)
return sb.toString();
return null;
}
public void myClose() throws IOException {
r.close();
}
@Override
public void close() throws IOException {
r.close();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return r.read(cbuf, off, len);
}
}</span></span></span></span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class MyBufferedReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
MyBufferedReader myBuf = new MyBufferedReader(fr);
// 按单个字符打印方式打印出数据
int i = 0;
while ((i = myBuf.myRead()) != -1) {
System.out.print((char) i);
}
// 按一行字符打印方式打印出数据
String line = null;
while ((line = myBuf.myReadLine()) != null) {
System.out.println(line);
}
myBuf.myClose();
}
}</span></span></span></span></span></span>
装饰设计模式:
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有功能,并提供加强功能,称该类为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。装饰和继承都能实现一样的特点:进行功能的扩展增强,但是装饰比继承灵活,装饰的特点:装饰类和被装饰类都
必须所属同一个接口或者父类。避免了继承体系臃肿,降低了类与类之间的关系。
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class LineNumberReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("Demo.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(100);
while ((line = lnr.readLine()) != null) {
System.out.println(lnr.getLineNumber() + ":" + line);
}
lnr.close();
}
}</span></span></span></span></span></span>
转换流适用原则:
1. 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。提高对文本操作的便捷。
2. 一旦操作文本涉及到具体的指定编码表时,必须使用转换流 。
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class TransStreamDemo {
public static void main(String[] args) throws IOException, IOException {
writeText_2();
writeText_3();
}
public static void readText_2() throws IOException, FileNotFoundException {
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"demo.txt"), "utf-8");
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_3() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"u8_1.txt"), "utf-8");
osw.write("你好");
osw.close();
}
public static void writeText_2() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"gbk_3.txt"), "GBK");
// FileWriter fw = new FileWriter("gbk_3.txt");
/*
* 两句代码的功能等同 FileWriter其实就是转换流指定了本机默认码表的体现,而且这个转换流的子类对象可以方便操作文本文件
* 即FileReader/FileWriter = InputStreamReader/OutputStreamWriter +
* 本机默认的编码表 如果操作的文件需要明确具体的编码,就必须用转换流
*/
osw.write("你好");
osw.close();
}
}</span></span></span></span></span></span>
递归:函数自身直接或间接调用到自身
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">/*
* 对指定目录进行所有内容的列出。
*/
public class FileTest {
public static void main(String[] args) {
File dir = new File("d:\\workspace");
// 传入初始文件目录及相应层级
listAll(dir, 0);
}
public static void listAll(File dir, int level) {
// 打印传入的文件目录下文件名称
System.out.println(getSpace(level) + dir.getName());
// 层级++
level++;
// 获取指定目录下当前所有文件夹或者文件对象
File[] files = dir.listFiles();
// 便利对象,判断是否包含文件,是,则返回调用listAll方法,否,则打印
for (int x = 0; x < files.length; x++) {
if (files[x].isDirectory()) {
listAll(files[x], level);
} else
System.out.println(getSpace(level) + files[x].getName());
}
}
private static String getSpace(int level) {
StringBuilder sb = new StringBuilder();
sb.append("|--");
for (int x = 0; x < level; x++) {
sb.insert(0, "| ");
}
return sb.toString();
}
}</span></span></span></span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class RemoveDirTest {
public static void main(String[] args) throws IOException {
File dir = new File("e:\\demodir");
removeDir(dir);
}
public static void removeDir(File dir) throws IOException {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
removeDir(file);
} else {
System.out.println(file + ":" + file.delete());
}
System.out.println(file + ":" + file.delete());
}
}
}</span></span></span></span></span>
Map
|--Hashtable
|--Properties:
Properties集合:
特点:
1,该集合中的键和值都是字符串类型。
2,集合中的数据可以保存到流中,或者从流获取。
通常该集合用于操作以键值对形式存在的配置文件。
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">public class PropertiesTest {
/**
* @param args
* @throws IOException
* @throws Exception
*/
public static void main(String[] args) throws IOException {
getAppCount();
}
public static void getAppCount() throws IOException {
// 将配置文件封装成File对象。
File confile = new File("count.properties");
if (!confile.exists()) {
confile.createNewFile();
}
FileInputStream fis = new FileInputStream(confile);
Properties prop = new Properties();
prop.load(fis);
// 从集合中通过键获取次数。
String value = prop.getProperty("time");
// 定义计数器。记录获取到的次数。
int count = 0;
if (value != null) {
count = Integer.parseInt(value);
if (count >= 5) {
// System.out.println("使用次数已到,请注册,给钱!");
// return;
throw new RuntimeException("使用次数已到,请注册,给钱!");
}
}
count++;
// 将改变后的次数重新存储到集合中。
prop.setProperty("time", count + "");
FileOutputStream fos = new FileOutputStream(confile);
prop.store(fos, "");
fos.close();
fis.close();
}
}</span></span></span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;"><span style="font-family:Arial;font-size:12px;"><span style="font-family:Arial;font-size:12px;">/*
* 简单说,就是建立一个指定扩展名的文件的列表。
*
* 思路:
* 1,必须进行深度遍历。
* 2,要在遍历的过程中进行过滤。将符合条件的内容都存储到容器中。
* 3,对容器中的内容进行遍历并将绝对路径写入到文件中。
*/
public class Test {
public static void main(String[] args) throws IOException {
File dir = new File("d:\\java");
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
};
List<File> list = new ArrayList<File>();
getFiles(dir, filter, list);
File destFile = new File(dir, "javalist.txt");
write2File(list, destFile);
}
/**
* 对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤, 将过滤后的内容存储到指定容器List中。
*
* @param dir
* @param filter
* @param list
*/
public static void getFiles(File dir, FilenameFilter filter, List<File> list) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
// 递归啦!
getFiles(file, filter, list);
} else {
// 对遍历到的文件进行过滤器的过滤。将符合条件File对象,存储到List集合中。
if (filter.accept(dir, file.getName())) {
list.add(file);
}
}
}
}
public static void write2File(List<File> list, File destFile)
throws IOException {
BufferedWriter bufw = null;
try {
bufw = new BufferedWriter(new FileWriter(destFile));
for (File file : list) {
bufw.write(file.getAbsolutePath());
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
throw new RuntimeException("写入失败");
} finally {
if (bufw != null)
try {
bufw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败");
}
}
}
}</span></span></span></span></span>
PrintStream:提供打印方法对多种数据类型值进行打印,并保持数据的表现形式,即保证数据原样性;不抛IOException
'\n'
) 时都会刷新输出缓冲区<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;">public class SequenceDemo {
public static void main(String[] args) throws IOException {
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("3.txt"));
//返回v的组件的枚举,生成Enumeration对象
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("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();
}
}</span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;">public 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 <= 3; x++) {
al.add(new FileInputStream("splitFiles\\" + x + ".part"));
}
final Iterator<FileInputStream> it = al.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("splitFiles\\eagle1.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("eagle_copy.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("splitFiles\\" + (count++) + ".part");
fos.write(buf, 0, len);
fos.close();
}
fis.close();
}
}</span></span></span>
需求:切割合并文件流和配置文件
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;">public class MergeFile {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File dir = new File("partFiles");
mergeFile_2(dir);
}
// 根据配置文件合并分割文件
public static void mergeFile_2(File dir) throws IOException {
/*
* 获取指定目录下的配置文件对象。
*/
// 自定义扩展名过滤器,实现了FilenameFilter
File[] files = dir.listFiles(new SuffixFilter(".properties"));
if (files.length != 1)
throw new RuntimeException(dir + ",该目录下没有properties扩展名的文件或者不唯一");
// 记录配置文件对象。
File confile = files[0];
// 获取该文件中的信息================================================。
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(confile);
prop.load(fis);
String filename = prop.getProperty("filename");
int count = Integer.parseInt(prop.getProperty("partcount"));
// 获取该目录下的所有碎片文件。 ==============================================
File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
if (partFiles.length != (count - 1)) {
throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该" + count + "个");
}
// 将碎片文件和流对象关联 并存储到集合中。
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int x = 0; x < partFiles.length; x++) {
al.add(new FileInputStream(partFiles[x]));
}
// 将多个流合并成一个序列流。
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(new File(dir, filename));
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 mergeFile(File dir) throws IOException {
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int x = 1; x <= 3; x++) {
al.add(new FileInputStream(new File(dir, x + ".part")));
}
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(new File(dir, "1.bmp"));
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}</span></span></span>
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;">public class SplitFileDemo {
private static final int SIZE = 1024 * 1024;
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
File file = new File("eagle_copy.mp3");
splitFile_2(file);
}
private static void splitFile_2(File file) throws IOException {
// 用读取流关联源文件。
FileInputStream fis = new FileInputStream(file);
// 定义一个1M的缓冲区。
byte[] buf = new byte[SIZE];
// 创建目的。
FileOutputStream fos = null;
int len = 0;
int count = 1;
/*
* 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。
* 这个信息为了进行描述,使用键值对的方式。用到了properties对象
*/
Properties prop = new Properties();
File dir = new File("partFiles");
if (!dir.exists())
dir.mkdirs();
while ((len = fis.read(buf)) != -1) {
fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buf, 0, len);
fos.close();
}
// 将被切割文件的信息保存到prop集合中。
prop.setProperty("partcount", count + "");
prop.setProperty("filename", file.getName());
fos = new FileOutputStream(new File(dir, count + ".properties"));
// 将prop集合中的数据存储到文件中。
prop.store(fos, "save file info");
fos.close();
fis.close();
}
public static void splitFile(File file) throws IOException {
// 用读取流关联源文件。
FileInputStream fis = new FileInputStream(file);
// 定义一个1M的缓冲区。
byte[] buf = new byte[SIZE];
// 创建目的。
FileOutputStream fos = null;
int len = 0;
int count = 1;
File dir = new File("partFiles");
if (!dir.exists())
dir.mkdirs();
while ((len = fis.read(buf)) != -1) {
fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buf, 0, len);
}
fos.close();
fis.close();
}
}</span></span></span>
3. 自定义过滤文件名类
<span style="font-size:12px;"><span style="font-size:12px;"><span style="font-size:12px;">public class SuffixFilter implements FilenameFilter {
private String suffix;
public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}</span></span></span>