打印流:PrintWriter,PrintStream--可以直接操作输入流和文件。
PrintWriter:字符打印流。
构造函数:
1,字符串路经。
2,File对象。
3,字符输出流。
4,字节输出流。
PrintStream:提供了打印方法可以对多种数据类型值进行打印,并保持数据的表现形式,不抛IOException。
public static void main(String[] args) throws IOException {
/*
* PrintStream:
* 1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。
* 2,它不抛IOException.
*
* 构造函数,接收三种类型的值:
* 1,字符串路径。
* 2,File对象。
* 3,字节输出流。
*/
PrintStream out = new PrintStream("print.txt");
// int by = read();
// write(by);
// out.write(610);//只写最低8位,
out.print(97);//将97先变成字符保持原样将数据打印到目的地。
out.close();
}
运行:
SequenceInputStream:序列流--对多个流进行合并。
public class SequenceInputStreamDemo {
public static void main(String[] args) throws IOException {
/*
* 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
*/
// Vector v = new Vector();
// v.add(new FileInputStream("1.txt"));
// v.add(new FileInputStream("2.txt"));
// v.add(new FileInputStream("3.txt"));
// Enumeration en = v.elements();
ArrayList al = new ArrayList();
for(int x=1; x<=3; x++){
al.add(new FileInputStream(x+".txt"));
}
Enumeration en = Collections.enumeration(al);
/*
final Iterator it = al.iterator();
Enumeration en = new Enumeration(){
@Override
public boolean hasMoreElements() {
return it.hasNext();
}
@Override
public FileInputStream nextElement() {
return it.next();
}
};*/
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("1234.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
运行:
切割文件:
public class SplitFileDemo {
private static final int SIZE = 1024 * 1024;
public static void main(String[] args) throws Exception {
File file = new File("c:\\a.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("c:\\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("c:\\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();
}
}
运行:
合并文件:
public class MergeFile {
public static void main(String[] args) throws IOException {
File dir = new File("c:\\partfiles");
mergeFile_2(dir);
}
public static void mergeFile_2(File dir) throws IOException {
/*
* 获取指定目录下的配置文件对象。
*/
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 al = new ArrayList();
for(int x=0; x 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 al = new ArrayList();
for(int x=1; x<=3 ;x++){
al.add(new FileInputStream(new File(dir,x+".part")));
}
Enumeration en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(new File(dir,"2.mp3"));
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
运行:
ObjectInputStream与ObjectOutputStream:操作对象,但是被操作的对象需要实现Serializable。
Serializable:用于给被序列化的类加入ID号,用于判断类和对象是否是同一个版本。
public class Person implements Serializable/*标记接口*/ {
private static final long serialVersionUID=9527l;//Serializable使得类每次改动都会生成不同的序列号,所以会发生InvalidClassException.这里给固定一个序列,解决问题。
private String name;//可改动变量修饰符试一下是否抛出InvalidClassException.
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
// writeObj();
readObj();
}
public static void readObj() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
//对象的反序列化。
Person p = (Person)ois.readObject();
System.out.println(p.getName()+":"+p.getAge());
ois.close();
}
public static void writeObj() throws IOException, IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
//对象序列化。 被序列化的对象必须实现Serializable接口。
oos.writeObject(new Person("小强",30));
oos.close();
}
}
运行:
transient:非静态数据不想序列化可使用这个关键字修饰。
writeObject:对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都可被写入。
public class Person implements Serializable/*标记接口*/ {
/**
* transient:非静态数据不想被序列化可以使用这个关键字修饰。
*/
private static final long serialVersionUID = 9527l;
private transient String name;
private static int age;//静态不可被写入
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
// writeObj();
readObj();
}
public static void readObj() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
//对象的反序列化。
Person p = (Person)ois.readObject();
System.out.println(p.getName()+":"+p.getAge());
ois.close();
}
public static void writeObj() throws IOException, IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
//对象序列化。 被序列化的对象必须实现Serializable接口。
oos.writeObject(new Person("小强",30));
oos.close();
}
}
运行:
RandomAccessFile:随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问。
因为可以随机写入,所以写文件可用多线程同时进行读写操作。
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
/*
RandomAccessFile:
1,该对象既能读,又能写
2,该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
3,可以通过getFilePointer方法获取指针位置,通过seek方法设置指针位置
4,其实该对象就是将字节输入流和输出流进行了封装。
5,该对象的源或者目的只能是文件。可通过构造函数看出。
*/
// writeFile();
readFile();
}
public static void readFile() throws IOException {
RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");
byte[] buf=new byte[4];
raf.read(buf);
String name=new String(buf);
int age=raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
//使用RandomAccessFile对象写入一些人员信息,比如姓名,年龄
public static void writeFile() throws IOException {
// 如果文件不存在,则创建,存在则不创建
RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");//rw:打开以便读取和写入,若文件不存在,尝试创建
raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("小强".getBytes());
raf.writeInt(99);
raf.close();
}
}
运行:
public static void randomWrite() throws IOException {
RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");
//往指定位置写入数据
raf.seek(3*8);
raf.write("哈哈".getBytes());
raf.writeInt(108);
raf.close();
}
public static void readFile() throws IOException {
RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");
//通过seek设置指针的位置
raf.seek(1*8);//随机读取,只要指定指针位置即可
byte[] buf=new byte[4];
raf.read(buf);
String name=new String(buf);
int age=raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
System.out.println("pos="+raf.getFilePointer());
raf.close();
}
运行:
PipedInputStream,PipedOutputStream:管道流,输入输出可以直接进行连接,通过结合线程使用。
public class PipedStream {
public static void main(String[] args) throws IOException {
PipedInputStream input=new PipedInputStream();
PipedOutputStream output=new PipedOutputStream();
input.connect(output);
new Thread(new Input(input)).start();
new Thread(new Output(output)).start();
}
}
class Input implements Runnable{
private PipedInputStream in;
Input(PipedInputStream in){
this.in = in;
}
public void run(){
try {
byte[] buf = new byte[1024];
int len = in.read(buf);
String s = new String(buf,0,len);
System.out.println("s="+s);
in.close();
} catch (Exception e) {
}
}
}
class Output implements Runnable{
private PipedOutputStream out;
Output(PipedOutputStream out){
this.out = out;
}
public void run(){
try {
Thread.sleep(5000);
out.write("hi,管道来了!".getBytes());
} catch (Exception e) {
}
}
}
运行:
DataInputStream,DataOutputStream:操作基本数据类型。
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
writeData();
readData();
}
public static void readData() throws IOException {
DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
String str=dis.readUTF();
System.out.println(str);
}
public static void writeData() throws IOException {
DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("你好");
dos.close();
}
}
运行:
ByteArrayReader,CharArrayWrite:操作字节数组。
CharArrayReader,CharArrayWrite:操作字符数组。
StringReader,StringWriter:操作字符串。
public class ByteArrayStreamDemo {
public static void main(String[] args) {
ByteArrayInputStream bis=new ByteArrayInputStream("abcdef".getBytes());
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int ch=0;
while((ch=bis.read())!=-1){
bos.write(ch);
}
System.out.println(bos.toString());
}
}
运行:
字符编码:字符流的出现是为了方便操作字符,更重要的是加入了编码转换--通过子类转换流完成--InputStreamReader,OutputStreamWriter。在两个对象进行构造的时候可以加入字符集。
public class EncodeDemo {
public static void main(String[] args) throws IOException {
/*
字符串 -->字节数组:编码。
字节数组 -->字符串:解码。
*/
String str="谢谢";
byte[] buf=str.getBytes("gbk");
String s1=new String(buf,"UTF-8");
System.out.println("s1="+s1);
byte[] buf2=s1.getBytes("UTF-8");//获取源字节。
printBytes(buf2);
String s2=new String(buf2,"GBK");
System.out.println("s2="+s2);
encodeDemo(str);
}
public static void encodeDemo(String str) throws UnsupportedEncodingException {
//编码
byte[] buf=str.getBytes("UTF-8");
printBytes(buf);
//解码
String s1=new String(buf,"UTF-8");
System.out.println("s1="+s1);
}
public static void printBytes(byte[] buf) {
for(byte b:buf){
System.out.print(b+" ");
}
}
}
运行:
联通问题(utf-8修改版字节表现形式):
原因:保存时,默认系统编码方式,打开时以utf-8的方式打开。
验证:
public class LianTong {
public static void main(String[] args) throws IOException {
String str="联通";
byte[] buf=str.getBytes("gbk");
for(byte b:buf){
System.out.println(Integer.toBinaryString(b&255));
}
}
}
运行:
截取字符:
public class Test {
public static void main(String[] args) throws IOException {
String str="ab你好cd谢谢";
// str="ab琲琲cd琲琲";
/*int len=str.getBytes("gbk").length;
for(int x=0;x=0;x--){
if(buf[x]<0)
count++;
else
break;
}
if(count%3==0)
return new String(buf,0,len,"utf-8");
else if(count%3==1)
return new String(buf,0,len-1,"utf-8");
else
return new String(buf,0,len-2,"utf-8");
}
public static String cutStringByByte(String str, int len) throws IOException {
byte[] buf=str.getBytes("gbk");
int count=0;
for(int x=len-1;x>0;x--){
if(buf[x]<0)
count++;
else
break;
}
if(count%2==0)
return new String(buf,0,len,"gbk");
else
return new String(buf,0,len-1,"gbk");
}
}
运行: