------- android培训、java培训、java学习型技术博客、期待与您交流! ----------
IO流
1、其他重要类
System:
out:标准输出,默认是控制台。
in:标准输入,默认是控制台
err:标准错误输出流,默认是控制台
setIn:可以改变输入设备
setOut:可以改变输出设备
System类不能实例化。
可以描述系统环境:
getProperties();
setProperty();
setProperties();
getProperty("os.name");
stringPropertiesName();
可以在启动jvm时加载系统信息。
Properties:
是Hashtable子类,
该集合中存储的都是字符串。没有泛型定义.
String getProperty(String key) 用指定的键在此属性列表中搜索属性。
void list(PrintStream out) 将属性列表输出到指定的输出流。
void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
Runtime类(单例):没有提供构造函数,不可以new对象。
static Runtime getRuntime();获得Runtime对象。
exec();//执行cmd命令
Process类:进程类 Runtime类exec方法返回该类。
Date类:时间操作类
DateFormat类:
SimpleDateFormat类:
日期和时间模式:
y 年
M 月
d 日
h 时
m 分
s 秒
E 星期中的天数 已经本地化了
如:
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Date d = new Date();
System.out.println(d);//打印的时间看不懂,希望有些格式。
//将模式封装到SimpleDateformat对象中。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
//调用format方法让模式格式化指定Date对象。
String time = sdf.format(d);
System.out.println("time="+time);
long l = System.currentTimeMillis();
Date d1 = new Date(l);
System.out.println("d1:"+d1);
}
}
Calender类:
获取年:Calender.get(Calender.YEAR);返回int
add(Calender.YEAR,4);
练习:
import java.util.*;
/*
两个练习:
1,获取任意年的二月有多少天。
思路:根据指定年设置一个时间就是
c.set(year,2,1)//某一年的3月1日。
c.add(Calenar.DAY_OF_MONTH,-1);//3月1日,往前推一天,就是2月最后一天。
2,获取昨天的现在这个时刻。
c.add(Calenar.DAY_OF_MONTH,-1);
*/
class CalendarDemo2
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
//c.set(2012,2,23);
c.add(Calendar.DAY_OF_MONTH,-18);
printCalendar(c);
}
public static void printCalendar(Calendar c)
{
String[] mons = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[] weeks = {
"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",
};
int index = c.get(Calendar.MONTH);
int index1 = c.get(Calendar.DAY_OF_WEEK);
sop(c.get(Calendar.YEAR)+"年");
//sop((c.get(Calendar.MONTH)+1)+"月");
sop(mons[index]);
sop(c.get(Calendar.DAY_OF_MONTH)+"日");
//sop("星期"+c.get(Calendar.DAY_OF_WEEK));
sop(weeks[index1]);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
Math类:
abs:绝对值
ceil:返回大于指定数据的最小整数
floor:返回小于指定数据的最大整数
round:四舍五入
pow:a^b a的b次方
random:返回伪随机数
Random类:随机类
nextInt();
练习:
/*
练习。给定一个小数。
保留该小数的后两位。
选作。可以考虑,保留时进行四舍五入。
*/
import java.util.*;
class MathDemo
{
public static void main(String[] args)
{
/*
Random r = new Random();
for(int x=0; x<10; x++)
{
//int d = (int)(Math.random()*10+1);
int d = r.nextInt(10)+1;
sop(d);
}
*/
saveTwo(12.3456,3,true);//12.34
}
public static void saveTwo(double d,int scale,boolean isRound)
{
double base = Math.pow(10,scale);
double num = isRound?Math.round(d*base)/base:((int)(d*base))/base;
sop("num="+num);
/*
double d1 = d*100;
sop("d1="+d1);
d1 = d1+0.5;
double d2 = (int)d1;
sop("d2="+d2);
double d3 = d2/100;
sop("d3="+d3);
*/
}
public static void show()
{
double d = Math.ceil(16.34);//ceil返回大于指定数据的最小整数。
double d1 = Math.floor(12.34);//floor返回小于指定数据的最大整数。
long l = Math.round(12.54);//四舍五入
sop("d="+d);
sop("d1="+d1);
sop("l="+l);
double d2 = Math.pow(2,3);
sop("d2="+d2);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
2、IO(Input Output)流
输入流、输出流
字节流基类:
InputStream OutputStream
字符流基类:
Reader Writer
IO流图结构:
图 2-1
字符流特点:
FileWriter
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");
//调用write方法,将字符串写入到流中。
fw.write("abcde");
//刷新流对象中的缓冲中的数据。
//将数据刷到目的地中。
//fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
//将数据刷到目的地中。
//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
fw.close();
}
}
IOException异常处理方式:
/*
IO异常的处理方式。
*/
import java.io.*;
class FileWriterDemo2
{
public static void main(String[] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("demo.txt");
fw.write("abcdefg");
}
catch (IOException e)
{
System.out.println("catch:"+e.toString());
}
finally
{
try
{
if(fw!=null)
fw.close();
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
文件的续写:
文件已经存在:
FileWriter(文件,true);//传递一个true参数,代表不覆盖文件,并对已有文件的末尾进行续写。
/*
演示对已有文件的数据续写。
*/
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args) throws IOException
{
//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
FileWriter fw = new FileWriter("demo.txt",true);
fw.write("nihao\r\nxiexie");
fw.close();
}
}
文本文件读取方式:
1、FileReader类
read():方法一次读取一个字符,而且会自动往下读。
返回-1则代表读取完毕。
2、通过字符数组进行读取:
read(char chs[]);
如:
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
FileReader fr = new FileReader("demo.txt");
//调用读取流对象的read方法。
//read():一次读一个字符。而且会自动往下读。
int ch = 0;
while((ch=fr.read())!=-1)
{
System.out.print((char)ch);
}
fr.close();
}
}
/*
第二种方式:通过字符数组进行读取。
*/
import java.io.*;
class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("demo.txt");
//定义一个字符数组。用于存储读到字符。
//该read(char[])返回的是读到字符个数。
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
fr.close();
}
}
Reader类:
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
int read(CharBuffer target) 试图将字符读入指定的字符缓冲区。
long skip(long n) 跳过字符。
Writer类:
Writer append(char c) 将指定字符添加到此 writer。
void write(char[] cbuf) 写入字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c) 写入单个字符。
void write(String str) 写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分。
abstract void flush() 刷新该流的缓冲。
复制:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class XuXie {
public static void main(String args[]) throws IOException{
FileWriter fw = new FileWriter("C:\\demo.txt");
FileReader fr = new FileReader("c:\\rajesh.txt");
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf))!=-1){
//复制
fw.write(buf, 0, num);
//打印在控制台上
System.out.print(new String(buf,0,num));
}
fr.close();
fw.close();
}
}
字符流的缓冲区:提高了对数据的读写效率。
BufferedWriter
newLine();跨平台换行;
BufferedReader
readLine();没有返回行终止字符,只返回有效字符。
缓冲区的出现时为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要先有流对象。
练习:通过缓冲区复制一个.txt文件。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedDemo {
public static void main(String[] args) throws IOException{
BufferedReader bur = new BufferedReader(new FileReader("c:\\rajesh.txt"));
BufferedWriter buw = new BufferedWriter(new FileWriter("c:\\22_copy.txt"));
String line = null;
while((line=bur.readLine())!=null){
buw.write(line);
buw.newLine();
buw.flush();
}
bur.close();
buw.close();
}
}
原理:图解
编写自己的readLine方法:
class MyBufferedReader extends Reader{
private Reader r;
MyBufferedReader(Reader r){
this.r = r;
}
//自定义readLine方法。
public String myReadLine() throws IOException{
//定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
sb.append((char)ch);
}
if(sb.length()!=0){
return sb.toString();
}
return null;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return r.read();
}
@Override
public void close() throws IOException {
r.close();
}
装饰设计模式:就是对已有的对象的功能进行增强。
使用场景:
1、当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。
2、适应于某个对象的职责经常发生变化或者经常需要动态的增加职责,避免因为这种为了适应这样的变化,而增加继承子类扩展的方式,因为
这种方式为 造成,子类膨胀的速度过快,难以控制。
装饰和继承的区别:
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。
BufferedReader的子类:
LineNumberReader:可以跟踪行号的缓冲字符输入流。
练习:模拟一个带行号的装饰类
package cn.itcast.test;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class MyLineNumberDemo {
/**
* @param args
*/
public static void main(String[] args) throws IOException{
MyLineNumberReader mr = new MyLineNumberReader(new FileReader("c:\\OutlookExpressLog1.txt"));
String line = null;
mr.setLineNumber(100);
while((line=mr.myReadLine())!=null){
System.out.println(mr.getLineNumber()+" "+line);
}
mr.close();
}
}
class MyLineNumberReader extends MyBufferedReader{
private int lineNumber;
MyLineNumberReader(Reader r) {
super(r);
}
public String myReadLine() throws IOException{
lineNumber++;
return super.myReadLine();
}
public int getLineNumber() {
return lineNumber;
}
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
}
字节流
InputStream
int available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
abstract int read() 从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。
OutputStream
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b) 将指定的字节写入此输出流。
基本操作与字符流类相同,但它不仅可以操作字符,还可以操作其他媒体文件。
字节流File读写操作.
FileOutputStream和FileInputStream
getBytes();方法。
FileInputStream
available();获取字符个数。
FileInputStream fis = null;
try {
fis = new FileInputStream("c:\\rajesh.txt");
byte[] bys = new byte[fis.available()];//定义一个刚好的缓冲区,避免循环。
fis.read(bys);
System.out.println(new String(bys));
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
复制图片:
/*
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
*/
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("c:\\2.bmp");
fis = new FileInputStream("c:\\1.bmp");
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
自定义缓存区
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int.
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面补了24个0,变成了int类型的数值。
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
00000000 00000000 00000000 11111111
而在写入数据时,只写该int类型数据的最低8位。
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024*4];
private int pos = 0,count = 0;
MyBufferedInputStream(InputStream in)
{
this.in = in;
}
//一次读一个字节,从缓冲区(字节数组)获取。
public int myRead()throws IOException
{
//通过in对象读取硬盘上数据,并存储buf中。
if(count==0)
{
count = in.read(buf);
if(count<0)
return -1;
pos = 0;
byte b = buf[pos];
count--;
pos++;
return b&255;//强制提升
}
else if(count>0)
{
byte b = buf[pos];
count--;
pos++;
return b&0xff;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
read方法在提升,write方法在强转。
读取键盘录入:
\r 13 \n 10;
mp3复制,通过缓冲区。
/*
演示mp3的复制。通过缓冲区。
BufferedOutputStream
BufferedInputStream
*/
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy_2();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
public static void copy_2()throws IOException
{
MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("c:\\9.mp3"));//通过自定义的缓冲区读取流
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\3.mp3"));
int by = 0;
//System.out.println("第一个字节:"+bufis.myRead());
while((by=bufis.myRead())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.myClose();
}
//通过字节流的缓冲区完成复制。
public static void copy_1()throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.close();
}
}
字节流转换字符流
转换流
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
可以选择编码表读取
键盘录入:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
字符流转换字节流
OutputStreamWriter 可以指定编码表
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("1.txt"),"utf-8"));
通过三个明确来确定使用哪个流对象。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
异常的日志信息
printStackTrace(PrintStream ps);
系统信息
Properties类
Properties是hashtable的子类。
也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
是集合中和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。
那么在加载数据时,需要数据有固定格式:键=值。
---------------------------------------
File类
用来将文件或者文件夹封装成对象
构造函数
File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)
File.separator 分隔符
常见方法:
File类常见方法:
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回false。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息。
getName():
getPath():
getParent():
getAbsolutePath()
long lastModified()
long length()
判断文件对象是否是文件或者目的时,必须先判断该文件对象封装的内容是否存在。
通过exists判断。
list 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
listRoot 列出可用的文件系统根。
listFiles(FileFilter filter)或者(FilenameFilter filter) --重要
FilenameFilter文件名过滤
递归
递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身。
练习:
package cn.itcast.test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class FileListDemo {
/**
* @param args
*/
public static void main(String[] args) {
File dir = new File("f:\\example");
List<File> list = new ArrayList<File>();
fileToList(dir,list);
System.out.println(list.size());
String fileName = "c:\\demo.txt";
writeToList(list,fileName);
}
public static void fileToList(File dir,List<File> list){
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory()){
list.add(file);
fileToList(file,list);
}else{
list.add(file);
}
}
}
public static void writeToList(List<File> list,String fileName){
BufferedWriter buw = null;
try {
buw = new BufferedWriter(new FileWriter(fileName));
for(File f:list){
buw.write(f.getAbsolutePath());
buw.newLine();
buw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(buw!=null){
try {
buw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
内存溢出
效率不高
删除一个带内容的目录
public static void deleteDir(File dir){
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory()){
deleteDir(file);
}
file.delete();
}
dir.delete();
}
Properties类
具有Map集合特点
是集合和IO技术结合的集合容器
可以用于键值对形式的配置文件。
新方法
load(InputStream is);
load(Reader r);
list(OutputStream os);
store();
练习:计数器
/*
用于记录应用程序运行次数。
如果使用次数已到,那么给出注册提示。
很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。
下一次在启动该程序,又重新开始从0计数。
这样不是我们想要的。
程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。
所以要建立一个配置文件。用于记录该软件的使用次数。
该配置文件使用键值对的形式。
这样便于阅读数据,并操作数据。
键值对数据是map集合。
数据是以文件形式存储,使用io技术。
那么map+io -->properties.
配置文件可以实现应用程序数据的共享。
*/
import java.io.*;
import java.util.*;
class RunCount
{
public static void main(String[] args) throws IOException
{
Properties prop = new Properties();
File file = new File("count.ini");
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
prop.load(fis);
int count = 0;
String value = prop.getProperty("time");
if(value!=null)
{
count = Integer.parseInt(value);
if(count>=5)
{
System.out.println("您好,使用次数已到,拿钱!");
return ;
}
}
count++;
prop.setProperty("time",count+"");
FileOutputStream fos = new FileOutputStream(file);
prop.store(fos,"");
fos.close();
fis.close();
}
}
打印流
PrintWriter 可以自动刷新 字符打印流
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
4,字符输出流,Writer。
PrintWriter(OutputStream out, boolean autoFlush)
PrintStream 字节打印流
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
PrintStream(OutputStream out, boolean autoFlush)
序列流
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("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
//接收枚举类型
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\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();
}
}
List转换为枚举
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=1; x<=3; x++)
{
al.add(new FileInputStream("c:\\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();
}
};
切割文件
public static void splitFile()throws IOException
{
FileInputStream fis = new FileInputStream("c:\\1.bmp");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1)
{
fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
对象的序列化
ObjectInputStream
ObjectOutputStream
将堆内存上的对象存入硬盘上。
持久化存储
对象的持久化
可以操作基本数据类型
想要实现序列化需要实现Serializable接口
静态不能被序列化。
关键字:transient 也不能被序列化
管道流
PipedInputStream
PipedOutputStream
不建议使用单线程,因为容易死锁。
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedStreamDemo {
public static void main(String[] args) throws IOException {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos);
Read r = new Read(pis);
Write w = new Write(pos);
new Thread(r).start();
new Thread(w).start();
}
}
class Read implements Runnable{
private PipedInputStream pis;
Read(PipedInputStream pis){
this.pis = pis;
}
@Override
public void run() {
byte[] buf = new byte[1024];
int num = 0;
try {
while((num=pis.read(buf))!=-1){
System.out.println(new String(buf,0,num));
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(pis!=null){
try {
pis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class Write implements Runnable{
private PipedOutputStream pos;
Write(PipedOutputStream pos){
this.pos = pos;
}
@Override
public void run() {
try {
pos.write("asfjdsaklfads".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally{
if(pos!=null){
try {
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
随机访问文件中的内容
RandomAccessFile
直接继承Object
具备读和写的功能。
getFilePointer:获取指针位置
seek改变指针位置。
该类只能操作文件。
mode值:
r 只读,不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
rw 读写,操作的文件不存在,会自动创建。如果存则不会覆盖。
通过调整指针,随机访问任意数据
skipBytes:只能往前跳
可以随机位置上写。
可以实现数据的分段写入
IO包中的其他类
DataInputStream DataOutputStream
可以操作基本数据类型的流对象
writeUTF();
ByteArrayInputStream ByteArrayOutputStream
包含内部缓冲区
不涉及底层资源操作。
用流的读写思想来操作数组。
由于没有用到系统资源,所以不用进行close关闭。
在流操作规律讲解时:
源设备,
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。
writeTo(InputStream in);
StringReader StringWriter
字符编码:
转换流:
编码:字符串变成字节数组
String-->byte[]; str.getBytes(charsetName);
解码:字节数组变成字符串
byte[]-->String; new String(byte[],charsetName);
联通例子:
utf-8编码格式:
1110
10
10
110
10
0
------- android培训、 java培训、 java学习型技术博客、期待与您交流! ----------