java中的IO详解(下)

BufferedReader的小例子

注意: BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流,采用:

BufferedReader buf = new BufferedReader(  

                new InputStreamReader(System.in)); 

下面给一个实例:

import java.io.BufferedReader;  

import java.io.IOException;  

import java.io.InputStreamReader;  

 

/**  

 * 使用缓冲区从键盘上读入内容  

 * */ 

10 public class BufferedReaderDemo{  

11     public static void main(String[] args){  

12         BufferedReader buf = new BufferedReader(  

13                 new InputStreamReader(System.in));  

14         String str = null;  

15         System.out.println("请输入内容");  

16         try{  

17             str = buf.readLine();  

18         }catch(IOException e){  

19             e.printStackTrace();  

20         }  

21         System.out.println("你输入的内容是:" + str);  

22     }  

23 

运行结果:

请输入内容

dasdas

你输入的内容是:dasdas

Scanner

其实我们比较常用的是采用Scanner类来进行数据输入,下面来给一个Scanner的例子吧

24 import java.util.Scanner;  

25  

26 /**  

27  * Scanner的小例子,从键盘读数据  

28  * */ 

29 public class ScannerDemo{  

30     public static void main(String[] args){  

31         Scanner sca = new Scanner(System.in);  

32         // 读一个整数  

33         int temp = sca.nextInt();  

34         System.out.println(temp);  

35         //读取浮点数  

36         float flo=sca.nextFloat();  

37         System.out.println(flo);  

38         //读取字符  

39         //...等等的,都是一些太基础的,就不师范了。  

40     }  

41 

其实Scanner可以接受任何的输入流

下面给一个使用Scanner类从文件中读出内容

42 import java.io.File;  

43 import java.io.FileNotFoundException;  

44 import java.util.Scanner;  

45  

46 /**  

47  * Scanner的小例子,从文件中读内容  

48  * */ 

49 public class ScannerDemo{  

50     public static void main(String[] args){  

51  

52         File file = new File("d:" + File.separator + "hello.txt");  

53         Scanner sca = null;  

54         try{  

55             sca = new Scanner(file);  

56         }catch(FileNotFoundException e){  

57             e.printStackTrace();  

58         }  

59         String str = sca.next();  

60         System.out.println("从文件中读取的内容是:" + str);  

61     }  

62 

【运行结果】:

从文件中读取的内容是:这些文件中的内容哦!

数据操作流DataOutputStreamDataInputStream

63 import java.io.DataOutputStream;  

64 import java.io.File;  

65 import java.io.FileOutputStream;  

66 import java.io.IOException;  

67  

68 public class DataOutputStreamDemo{  

69     public static void main(String[] args) throws IOException{  

70         File file = new File("d:" + File.separator + "hello.txt");  

71         char[] ch = { 'A', 'B', 'C' };  

72         DataOutputStream out = null;  

73         out = new DataOutputStream(new FileOutputStream(file));  

74         for(char temp : ch){  

75             out.writeChar(temp);  

76         }  

77         out.close();  

78     }  

79 

A B C

现在我们在上面例子的基础上,使用DataInputStream读出内容

80 import java.io.DataInputStream;  

81 import java.io.File;  

82 import java.io.FileInputStream;  

83 import java.io.IOException;  

84  

85 public class DataOutputStreamDemo{  

86     public static void main(String[] args) throws IOException{  

87         File file = new File("d:" + File.separator + "hello.txt");  

88         DataInputStream input = new DataInputStream(new FileInputStream(file));  

89         char[] ch = new char[10];  

90         int count = 0;  

91         char temp;  

92         while((temp = input.readChar()) != 'C'){  

93             ch[count++] = temp;  

94         }  

95         System.out.println(ch);  

96     }  

97 

【运行结果】:

AB

合并流 SequenceInputStream

SequenceInputStream主要用来将2个流合并在一起,比如将两个txt中的内容合并为另外一个txt。下面给出一个实例:

98 import java.io.File;  

99 import java.io.FileInputStream;  

100 import java.io.FileOutputStream;  

101 import java.io.IOException;  

102 import java.io.InputStream;  

103 import java.io.OutputStream;  

104 import java.io.SequenceInputStream;  

105  

106 /**  

107  * 将两个文本文件合并为另外一个文本文件  

108  * */ 

109 public class SequenceInputStreamDemo{  

110     public static void main(String[] args) throws IOException{  

111         File file1 = new File("d:" + File.separator + "hello1.txt");  

112         File file2 = new File("d:" + File.separator + "hello2.txt");  

113         File file3 = new File("d:" + File.separator + "hello.txt");  

114         InputStream input1 = new FileInputStream(file1);  

115         InputStream input2 = new FileInputStream(file2);  

116         OutputStream output = new FileOutputStream(file3);  

117         // 合并流  

118         SequenceInputStream sis = new SequenceInputStream(input1, input2);  

119         int temp = 0;  

120         while((temp = sis.read()) != -1){  

121             output.write(temp);  

122         }  

123         input1.close();  

124         input2.close();  

125         output.close();  

126         sis.close();  

127     }  

128 

【运行结果】

结果会在hello.txt文件中包含hello1.txthello2.txt文件中的内容。

文件压缩 ZipOutputStream

先举一个压缩单个文件的例子吧:

129 import java.io.File;  

130 import java.io.FileInputStream;  

131 import java.io.FileOutputStream;  

132 import java.io.IOException;  

133 import java.io.InputStream;  

134 import java.util.zip.ZipEntry;  

135 import java.util.zip.ZipOutputStream;  

136  

137 public class ZipOutputStreamDemo1{  

138     public static void main(String[] args) throws IOException{  

139         File file = new File("d:" + File.separator + "hello.txt");  

140         File zipFile = new File("d:" + File.separator + "hello.zip");  

141         InputStream input = new FileInputStream(file);  

142         ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(  

143                 zipFile));  

144         zipOut.putNextEntry(new ZipEntry(file.getName()));  

145         // 设置注释  

146         zipOut.setComment("hello");  

147         int temp = 0;  

148         while((temp = input.read()) != -1){  

149             zipOut.write(temp);  

150         }  

151         input.close();  

152         zipOut.close();  

153     }  

154 

【运行结果】

运行结果之前,我创建了一个hello.txt的文件,原本大小56个字节,但是压缩之后产生hello.zip之后,居然变成了175个字节,有点搞不懂。
不过结果肯定是正确的,我只是提出我的一个疑问而已。

上面的这个例子测试的是压缩单个文件,下面的们来看看如何压缩多个文件。

155 import java.io.File;  

156 import java.io.FileInputStream;  

157 import java.io.FileOutputStream;  

158 import java.io.IOException;  

159 import java.io.InputStream;  

160 import java.util.zip.ZipEntry;  

161 import java.util.zip.ZipOutputStream;  

162  

163 /**  

164  * 一次性压缩多个文件  

165  * */ 

166 public class ZipOutputStreamDemo2{  

167     public static void main(String[] args) throws IOException{  

168         // 要被压缩的文件夹  

169         File file = new File("d:" + File.separator + "temp");  

170         File zipFile = new File("d:" + File.separator + "zipFile.zip");  

171         InputStream input = null;  

172         ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(  

173                 zipFile));  

174         zipOut.setComment("hello");  

175         if(file.isDirectory()){  

176             File[] files = file.listFiles();  

177             for(int i = 0; i < files.length; ++i){  

178                 input = new FileInputStream(files[i]);  

179                 zipOut.putNextEntry(new ZipEntry(file.getName()  

180                         + File.separator + files[i].getName()));  

181                 int temp = 0;  

182                 while((temp = input.read()) != -1){  

183                     zipOut.write(temp);  

184                 }  

185                 input.close();  

186             }  

187         }  

188         zipOut.close();  

189     }  

190 

【运行结果】

先看看要被压缩的文件吧:

接下来看看压缩之后的:

大家自然想到,既然能压缩,自然能解压缩,在谈解压缩之前,我们会用到一个ZipFile类,先给一个这个例子吧。java中的每一个压缩文件都是可以使用ZipFile来进行表示的

191 import java.io.File;  

192 import java.io.IOException;  

193 import java.util.zip.ZipFile;  

194  

195 /**  

196  * ZipFile演示  

197  * */ 

198 public class ZipFileDemo{  

199     public static void main(String[] args) throws IOException{  

200         File file = new File("d:" + File.separator + "hello.zip");  

201         ZipFile zipFile = new ZipFile(file);  

202         System.out.println("压缩文件的名称为:" + zipFile.getName());  

203     }  

204 

【运行结果】:

压缩文件的名称为:d:\hello.zip

现在我们呢是时候来看看如何加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件中只有一个文件的情况),我们采用前面的例子产生的压缩文件hello.zip

205 import java.io.File;  

206 import java.io.FileOutputStream;  

207 import java.io.IOException;  

208 import java.io.InputStream;  

209 import java.io.OutputStream;  

210 import java.util.zip.ZipEntry;  

211 import java.util.zip.ZipFile;  

212  

213 /**  

214  * 解压缩文件(压缩文件中只有一个文件的情况)  

215  * */ 

216 public class ZipFileDemo2{  

217     public static void main(String[] args) throws IOException{  

218         File file = new File("d:" + File.separator + "hello.zip");  

219         File outFile = new File("d:" + File.separator + "unZipFile.txt");  

220         ZipFile zipFile = new ZipFile(file);  

221         ZipEntry entry = zipFile.getEntry("hello.txt");  

222         InputStream input = zipFile.getInputStream(entry);  

223         OutputStream output = new FileOutputStream(outFile);  

224         int temp = 0;  

225         while((temp = input.read()) != -1){  

226             output.write(temp);  

227         }  

228         input.close();  

229         output.close();  

230     }  

231 

【运行结果】:
解压缩之前:

这个压缩文件还是175字节
解压之后产生:

又回到了56字节,表示郁闷。

现在让我们来解压一个压缩文件中包含多个文件的情况吧
ZipInputStream

当我们需要解压缩多个文件的时候,ZipEntry就无法使用了,如果想操作更加复杂的压缩文件,我们就必须使用ZipInputStream

232 import java.io.File;  

233 import java.io.FileInputStream;  

234 import java.io.FileOutputStream;  

235 import java.io.IOException;  

236 import java.io.InputStream;  

237 import java.io.OutputStream;  

238 import java.util.zip.ZipEntry;  

239 import java.util.zip.ZipFile;  

240 import java.util.zip.ZipInputStream;  

241  

242 /**  

243  * 解压缩一个压缩文件中包含多个文件的情况  

244  * */ 

245 public class ZipFileDemo3{  

246     public static void main(String[] args) throws IOException{  

247         File file = new File("d:" + File.separator + "zipFile.zip");  

248         File outFile = null;  

249         ZipFile zipFile = new ZipFile(file);  

250         ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file));  

251         ZipEntry entry = null;  

252         InputStream input = null;  

253         OutputStream output = null;  

254         while((entry = zipInput.getNextEntry()) != null){  

255             System.out.println("解压缩" + entry.getName() + "文件");  

256             outFile = new File("d:" + File.separator + entry.getName());  

257             if(!outFile.getParentFile().exists()){  

258                 outFile.getParentFile().mkdir();  

259             }  

260             if(!outFile.exists()){  

261                 outFile.createNewFile();  

262             }  

263             input = zipFile.getInputStream(entry);  

264             output = new FileOutputStream(outFile);  

265             int temp = 0;  

266             while((temp = input.read()) != -1){  

267                 output.write(temp);  

268             }  

269             input.close();  

270             output.close();  

271         }  

272     }  

273 

【运行结果】:
被解压的文件:

解压之后再D盘下会出现一个temp文件夹,里面内容:

PushBackInputStream回退流

274 import java.io.ByteArrayInputStream;  

275 import java.io.IOException;  

276 import java.io.PushbackInputStream;  

277  

278 /**  

279  * 回退流操作  

280  * */ 

281 public class PushBackInputStreamDemo{  

282     public static void main(String[] args) throws IOException{  

283         String str = "hello,rollenholt";  

284         PushbackInputStream push = null;  

285         ByteArrayInputStream bat = null;  

286         bat = new ByteArrayInputStream(str.getBytes());  

287         push = new PushbackInputStream(bat);  

288         int temp = 0;  

289         while((temp = push.read()) != -1){  

290             if(temp == ','){  

291                 push.unread(temp);  

292                 temp = push.read();  

293                 System.out.print("(回退" + (char) temp + ") ");  

294             }else{  

295                 System.out.print((char) temp);  

296             }  

297         }  

298     }  

299 

【运行结果】:
hello(回退,) rollenholt

300 /**  

301  * 取得本地的默认编码  

302  * */ 

303 public class CharSetDemo{  

304     public static void main(String[] args){  

305         System.out.println("系统默认编码为:" + System.getProperty("file.encoding"));  

306     }  

307 

【运行结果】:

系统默认编码为:GBK

乱码的产生:

308 import java.io.File;  

309 import java.io.FileOutputStream;  

310 import java.io.IOException;  

311 import java.io.OutputStream;  

312  

313 /**  

314  * 乱码的产生  

315  * */ 

316 public class CharSetDemo2{  

317     public static void main(String[] args) throws IOException{  

318         File file = new File("d:" + File.separator + "hello.txt");  

319         OutputStream out = new FileOutputStream(file);  

320         byte[] bytes = "你好".getBytes("ISO8859-1");  

321         out.write(bytes);  

322         out.close();  

323     }  

324 

【运行结果】:

??

一般情况下产生乱码,都是由于编码不一致的问题。

对象的序列化

对象序列化就是把一个对象变为二进制数据流的一种方法。

一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。

先让我们实现一个具有序列化能力的类吧:

325 import java.io.*;  

326 /**  

327  * 实现具有序列化能力的类  

328  * */ 

329 public class SerializableDemo implements Serializable{  

330     public SerializableDemo(){  

331           

332     }  

333     public SerializableDemo(String name, int age){  

334         this.name=name;  

335         this.age=age;  

336     }  

337     @Override 

338     public String toString(){  

339         return "姓名:"+name+"  年龄:"+age;  

340     }  

341     private String name;  

342     private int age;  

343 

这个类就具有实现序列化能力,

在继续将序列化之前,先将一下ObjectInputStreamObjectOutputStream这两个类

先给一个ObjectOutputStream的例子吧:

344 import java.io.Serializable;  

345 import java.io.File;  

346 import java.io.FileOutputStream;  

347 import java.io.IOException;  

348 import java.io.ObjectOutputStream;  

349  

350 /**  

351  * 实现具有序列化能力的类  

352  * */ 

353 public class Person implements Serializable{  

354     public Person(){  

355  

356     }  

357  

358     public Person(String name, int age){  

359         this.name = name;  

360         this.age = age;  

361     }  

362  

363     @Override 

364     public String toString(){  

365         return "姓名:" + name + "  年龄:" + age;  

366     }  

367  

368     private String name;  

369     private int age;  

370 }  

371 /**  

372  * 示范ObjectOutputStream  

373  * */ 

374 public class ObjectOutputStreamDemo{  

375     public static void main(String[] args) throws IOException{  

376         File file = new File("d:" + File.separator + "hello.txt");  

377         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(  

378                 file));  

379         oos.writeObject(new Person("rollen", 20));  

380         oos.close();  

381     }  

382 

【运行结果】:

当我们查看产生的hello.txt的时候,看到的是乱码,呵呵。因为是二进制文件。

虽然我们不能直接查看里面的内容,但是我们可以使用ObjectInputStream类查看:

383 import java.io.File;  

384 import java.io.FileInputStream;  

385 import java.io.ObjectInputStream;  

386  

387 /**  

388  * ObjectInputStream示范  

389  * */ 

390 public class ObjectInputStreamDemo{  

391     public static void main(String[] args) throws Exception{  

392         File file = new File("d:" + File.separator + "hello.txt");  

393         ObjectInputStream input = new ObjectInputStream(new FileInputStream(  

394                 file));  

395         Object obj = input.readObject();  

396         input.close();  

397         System.out.println(obj);  

398     }  

399 

【运行结果】

姓名:rollen 年龄:20

到底序列化什么内容呢?

其实只有属性会被序列化。

Externalizable接口

Serializable接口声明的类的对象的属性都将被序列化,但是如果想自定义序列化的内容的时候,就需要实现Externalizable接口。

当一个类要使用Externalizable这个接口的时候,这个类中必须要有一个无参的构造函数,如果没有的话,在构造的时候会产生异常,这是因为在反序列话的时候会默认调用无参的构造函数。

现在我们来演示一下序列化和反序列话:

400 package IO;  

401  

402 import java.io.Externalizable;  

403 import java.io.File;  

404 import java.io.FileInputStream;  

405 import java.io.FileOutputStream;  

406 import java.io.IOException;  

407 import java.io.ObjectInput;  

408 import java.io.ObjectInputStream;  

409 import java.io.ObjectOutput;  

410 import java.io.ObjectOutputStream;  

411  

412 /**  

413  * 序列化和反序列化的操作  

414  * */ 

415 public class ExternalizableDemo{  

416     public static void main(String[] args) throws Exception{  

417         ser(); // 序列化  

418         dser(); // 反序列话  

419     }  

420  

421     public static void ser() throws Exception{  

422         File file = new File("d:" + File.separator + "hello.txt");  

423         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(  

424                 file));  

425         out.writeObject(new Person("rollen", 20));  

426         out.close();  

427     }  

428  

429     public static void dser() throws Exception{  

430         File file = new File("d:" + File.separator + "hello.txt");  

431         ObjectInputStream input = new ObjectInputStream(new FileInputStream(  

432                 file));  

433         Object obj = input.readObject();  

434         input.close();  

435         System.out.println(obj);  

436     }  

437 }  

438  

439 class Person implements Externalizable{  

440     public Person(){  

441  

442     }  

443  

444     public Person(String name, int age){  

445         this.name = name;  

446         this.age = age;  

447     }  

448  

449     @Override 

450     public String toString(){  

451         return "姓名:" + name + "  年龄:" + age;  

452     }  

453  

454     // 复写这个方法,根据需要可以保存的属性或者具体内容,在序列化的时候使用  

455     @Override 

456     public void writeExternal(ObjectOutput out) throws IOException{  

457         out.writeObject(this.name);  

458         out.writeInt(age);  

459     }  

460  

461     // 复写这个方法,根据需要读取内容 反序列话的时候需要  

462     @Override 

463     public void readExternal(ObjectInput in) throws IOException,  

464             ClassNotFoundException{  

465         this.name = (String) in.readObject();  

466         this.age = in.readInt();  

467     }  

468  

469     private String name;  

470     private int age;  

471 

【运行结果】:

姓名:rollen 年龄:20

本例中,我们将全部的属性都保留了下来,

Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,

当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:

下面举一个例子:

472 package IO;  

473  

474 import java.io.File;  

475 import java.io.FileInputStream;  

476 import java.io.FileOutputStream;  

477 import java.io.ObjectInputStream;  

478 import java.io.ObjectOutputStream;  

479 import java.io.Serializable;  

480  

481 /**  

482  * 序列化和反序列化的操作  

483  * */ 

484 public class serDemo{  

485     public static void main(String[] args) throws Exception{  

486         ser(); // 序列化  

487         dser(); // 反序列话  

488     }  

489  

490     public static void ser() throws Exception{  

491         File file = new File("d:" + File.separator + "hello.txt");  

492         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(  

493                 file));  

494         out.writeObject(new Person1("rollen", 20));  

495         out.close();  

496     }  

497  

498     public static void dser() throws Exception{  

499         File file = new File("d:" + File.separator + "hello.txt");  

500         ObjectInputStream input = new ObjectInputStream(new FileInputStream(  

501                 file));  

502         Object obj = input.readObject();  

503         input.close();  

504         System.out.println(obj);  

505     }  

506 }  

507  

508 class Person1 implements Serializable{  

509     public Person1(){  

510  

511     }  

512  

513     public Person1(String name, int age){  

514         this.name = name;  

515         this.age = age;  

516     }  

517  

518     @Override 

519     public String toString(){  

520         return "姓名:" + name + "  年龄:" + age;  

521     }  

522  

523     // 注意这里  

524     private transient String name;  

525     private int age;  

526 

【运行结果】:

姓名:null 年龄:20

最后在给一个序列化一组对象的例子吧:

527 import java.io.File;  

528 import java.io.FileInputStream;  

529 import java.io.FileOutputStream;  

530 import java.io.ObjectInputStream;  

531 import java.io.ObjectOutputStream;  

532 import java.io.Serializable;  

533  

534 /**  

535  * 序列化一组对象  

536  * */ 

537 public class SerDemo1{  

538     public static void main(String[] args) throws Exception{  

539         Student[] stu = { new Student("hello", 20), new Student("world", 30),  

540                 new Student("rollen", 40) };  

541         ser(stu);  

542         Object[] obj = dser();  

543         for(int i = 0; i < obj.length; ++i){  

544             Student s = (Student) obj[i];  

545             System.out.println(s);  

546         }  

547     }  

548  

549     // 序列化  

550     public static void ser(Object[] obj) throws Exception{  

551         File file = new File("d:" + File.separator + "hello.txt");  

552         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(  

553                 file));  

554         out.writeObject(obj);  

555         out.close();  

556     }  

557  

558     // 反序列化  

559     public static Object[] dser() throws Exception{  

560         File file = new File("d:" + File.separator + "hello.txt");  

561         ObjectInputStream input = new ObjectInputStream(new FileInputStream(  

562                 file));  

563         Object[] obj = (Object[]) input.readObject();  

564         input.close();  

565         return obj;  

566     }  

567 }  

568  

569 class Student implements Serializable{  

570     public Student(){  

571  

572     }  

573  

574     public Student(String name, int age){  

575         this.name = name;  

576         this.age = age;  

577     }  

578  

579     @Override 

580     public String toString(){  

581         return "姓名:  " + name + "  年龄:" + age;  

582     }  

583  

584     private String name;  

585     private int age;  

586 

【运行结果】:

姓名: hello 年龄:20

姓名: world 年龄:30

姓名: rollen 年龄:40

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值