a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 138|回复: 1

[基础知识] Java流缓冲区问题

[复制链接]
发表于 2012-8-4 12:37:27 | 显示全部楼层 |阅读模式
先讲一下关于java缓冲区的知识,应用程序和IO设备之间存在一个缓冲区,一般流是没有缓冲区的,但是如果存在缓冲区,就会发现很大的问题。$ t' W& V9 w+ k) Z) [% Q# R
  错误代码如下:为了确保问题发生,我使用了BufferedOutputStream,使得手动构造出了一个缓冲区。
/ G& A) f: k7 kimport java.io.*;
6 J+ U% V2 A* B. }: apublic class Test {8 ~3 @+ y2 {) J9 |0 \, g7 w
    public static void main(String[] args) throws Exception{, H6 y& O6 W8 q+ s6 W8 C* U! ]: E
        DataOutputStream out = new DataOutputStream(
8 C& Z; w% p' T: [                            new BufferedOutputStream(; Q( ]) m, `9 p
                            new FileOutputStream("1.txt")));5 W4 O" o5 ]4 `% [$ |9 N/ Z6 J
        out.writeChars("hello");( b( A- i- p- H6 ]  @
        FileInputStream in = new FileInputStream("1.txt");( W5 q8 z& ^/ r! k: y2 R# U6 z
        int len = in.available();4 m& i1 i+ w* [1 [# U7 P
        byte[] b = new byte[len];" I. x! E4 T1 k
        int actlen = in.read(b);
. d- |! z4 @- R4 j        String str = new String(b);
( i& ~0 ^( N/ v0 T, i$ c; l" i        System.out.println(str);
4 Q" m1 r8 |6 |& i. P7 P$ Z    }3 c1 _: j/ u( Q0 q$ W! ?
}
8 B$ ~6 _- b9 ~  发现什么问题了吗?  f" z4 }+ t/ y5 d& j
  因为如果没有缓冲区,应用程序每次IO都要和设备进行通信,效率很低,因此缓冲区为了提高效率,当写入设备时,先写入缓冲区,等到缓冲区有足够多的数据时,就整体写入设备。这就是问题所在,上个例子中,当我们写入hello时,由于hello占用空间很小,所以暂时存放在缓冲区中,后来输入流想要从文件中读取,但是由于文件中没有字节,所以不能读取hello。* Z0 a$ |$ V9 j+ M
  这里,解决方法很简单,只要调用out.flush() 或者out.close()即可,这是把缓冲区的数据手动写入文件。
( ]2 d/ W4 b  v) u  T& [' [  正确代码如下:
) Q5 ?( t3 M$ n7 D0 c/ g2 A7 `import java.io.*;  X7 X0 g% C4 l/ C5 v
public class Test {% s( }- C" R6 b2 y5 q6 b
    public static void main(String[] args) throws Exception{! L# ]' j  m5 u& p* z, D
        DataOutputStream out = new DataOutputStream(; c* N  b- S0 f* F& Z, s) T
                            new BufferedOutputStream(
$ o, l$ _; `; b4 E4 z                            new FileOutputStream("1.txt")));
5 f) Q+ ]. D' Y+ Z- g2 h' m        out.writeChars("hello");: v! Y( I% J0 R& L0 l! h/ Y
        out.close();//inserted/ @( A/ g* i% H! @. J0 t
        FileInputStream in = new FileInputStream("1.txt");) Q3 \, F  b+ ~3 g) v3 `
        int len = in.available();
- J& b) f  M0 k( ], H0 B$ q        byte[] b = new byte[len];
+ F" ^& I, @9 o; ?$ C) o% H        int actlen = in.read(b);
8 ?3 C& T5 f& `: P        String str = new String(b);
3 B: |0 q- @2 U        System.out.println(str);
) ?! g# [2 k8 `, l
; ~# G' M* S+ J' l" [# L- n2 x    }
6 _3 T; J0 E  h}
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:37:28 | 显示全部楼层

Java流缓冲区问题

</p>接下来又是我遇到的一个例子,这个例子也很明显的反应出缓冲区的问题。
9 E3 F+ f/ X1 s+ v- {5 X5 |; b) rimport java.io.BufferedReader;8 u2 O( i* S# m  S1 ^
import java.io.FileReader;
$ K% \. D% s- d: w- vimport java.io.FileWriter;' ?2 s0 i) n) h; [/ ]4 v
import java.io.IOException;
" @  J* j  Y) p5 Y# _import java.io.PrintWriter;
0 R# A# t/ V5 Z: k6 y. |3 w8 rimport java.util.Calendar;
1 \; k+ ~0 T9 d# [# Uimport java.util.Date;4 w! m" R  |% c7 A2 y
import java.util.GregorianCalendar;2 ^# n" c% U! S/ j! T
import java.util.Scanner;
! w6 N/ O. y* G" x9 p6 yimport java.util.StringTokenizer;
' v8 j  q2 G7 W" \/ e9 w" J4 Hpublic class StringTokenizerTest {
; w7 J1 f6 y- V* M: J9 R$ |0 L5 _    public static void main(String[] args) {
" X" B4 n/ y; M' F/ O. |, f/ j        Employee[] e = new Employee[3];# k4 z, F6 W: f0 S8 F
        e[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
  ~: m' B! d5 ^4 z6 |        e[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);. p+ h5 ^* [9 O( V# r
        e[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
9 `2 y, p  P1 M3 S) O1 i5 p7 i4 U        try {
- I  J2 r% V  h; k/ W            PrintWriter out = new PrintWriter(new FileWriter("1.txt"));0 B: m3 {8 C% q' v8 t, p3 Q3 o
            writeData(e, out);" I( }0 t5 `& Y, B' s
            // out.close();**********************************************************************
5 s2 V! r+ S) ~( F        } catch (Exception e1) {1 U. h; B" M; R4 |
            e1.printStackTrace();
/ y4 P! P! w" ]# e        }! s2 E; M4 ~* b3 s
        System.out.println("*******是否要读取数据?********");
: h; g* ~3 L, i$ i        Scanner in1 = new Scanner(System.in);6 z  J& m1 g/ |' Y0 p# u9 [9 A
        String yes = in1.nextLine();
+ u" @+ c2 _2 M        if (yes.equalsIgnoreCase("YES")) {. r6 _6 `: R! ]: y
            try {
* C! L' T2 O+ d7 O- f                BufferedReader in = new BufferedReader(new FileReader("1.txt"));
" T7 `2 X# u" Q, b                Employee[] result = readData(in);+ K. ~3 f/ \$ J) M% |2 p  k: U
                for (int i = 0; i < result.length; i++)
& _* e/ z4 k0 `" P  _: G1 B9 A  H  `                    System.out.println(result);, h3 m- a$ Y* M8 {' q# b6 ?
                in.close();; |7 L! {$ Z% c: F) z) R6 }: ~" H
            } catch (Exception e2) {
! R4 i3 V$ I, }                e2.printStackTrace();
) j6 a$ R2 K/ \7 i& c% R' `; D            }
7 N0 u( n4 L/ p        }
3 a# O" g3 G# o( `- z& t9 ~: W, ?. b    }
# a4 i/ ?0 p! a) c/ s9 ?    public static Employee[] readData(BufferedReader in) throws IOException {
2 u# P$ Y) F9 I9 e! V' L" }        int length = Integer.parseInt(in.readLine());
% z: s6 [" p, ^        Employee[] e = new Employee[length];
2 q9 x/ T0 Q2 N3 i% j        for (int i = 0; i < length; i++) {/ ^, b; n5 r5 h: w) l
            String line = in.readLine();
$ ~! u0 `0 d  [$ G            StringTokenizer token = new StringTokenizer(line, "|");
+ R2 E9 e9 N* N" `/ ?7 }. A            String name = token.nextToken();; d* o2 y7 v& i
            double salary = Double.parseDouble(token.nextToken());$ n) t; U$ M5 x8 s: A; w
            int year = Integer.parseInt(token.nextToken());# O  o( Z, Q: Q9 j% W
            int month = Integer.parseInt(token.nextToken());
9 B4 S$ F0 z5 d. ?+ s% l1 l3 {            int day = Integer.parseInt(token.nextToken());+ f4 s2 b# n8 H2 Y4 A
            e = new Employee(name, salary, year, month, day);
& O: D2 J4 |- K        }' M( J. A/ l' A5 u+ N
        return e;. Y2 f0 o( o* P% `. l, h
    }
# @' u; \: w0 _) i; s* N    public static void writeData(Employee[] e, PrintWriter out) {
( \! ?9 G, e/ ~" ?        out.println(e.length);. t6 U2 n2 ]# A: z( a8 k# u8 O/ l; {
        for (int i = 0; i < e.length; i++) {
! N# u0 R  m+ b  d) ~/ c" m5 y            String name = e.getName();0 ^& l- k4 O; J6 u
            double salary = e.getSalary();3 L& f- `' T0 T* c
            Date date = e.getHireDay();
1 T% E& z- U- X9 ~            Calendar c = new GregorianCalendar();
& C# Y; T) X1 \! b            c.setTime(date);8 c6 r$ e9 d6 K3 n( O
            int year = c.get(Calendar.YEAR);! h( g% q- B% w! @
            int month = c.get(Calendar.MONTH) + 1;
/ \7 f. W& D, Q1 Q9 J, c            int day = c.get(Calendar.DAY_OF_MONTH);% ~  y2 d0 f- S2 p5 w
            out.println(name + "|" + salary + "|" + year + "|" + month + "|"
+ z' s6 l  P4 I+ o! g  K) Y+ [                    + day);
0 @6 Y( y, n1 H9 _7 S        }* T! }/ N' x0 O. y# `4 _
        System.out.println("********写入数据完毕********");  E. G' {) p, z# U6 J, x2 y
    }5 l. G6 r7 ?3 m
}5 e7 G  l! a6 P
class Employee {
$ n- |1 m. E- n6 j    public Employee(String n, double s, int year, int month, int day) {& B: X7 _+ b* D
        name = n;( [/ T; j4 ?4 z+ c8 y8 h7 _+ ?
        salary = s;
* t, T* y; Y" O5 V) e) j: j        GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
$ a) z' i; B$ k6 Q2 w        hireDay = calendar.getTime();
  \' j4 d" E$ y    }
: x  ]+ U+ z- _6 J    public String getName() {4 c( ^8 G5 D- x1 g2 F, }) n( k
        return name;
+ n. p9 M, C9 [) j+ X0 g    }9 W7 m4 g4 l" K6 X2 o
    public double getSalary() {  b8 k% q7 }, P" y! ]
        return salary;8 u) m% c  T" u  t; m& \0 R5 m( k! D
    }
/ b; V8 a4 r3 A/ R4 J    public Date getHireDay() {
0 M. p, e3 o' X' Q( O$ C        return hireDay;, _& c9 d0 m! @$ j
    }
, U9 h$ T# c& ^% z    public void raiseSalary(double byPercent) {9 G$ [( P  m+ u$ ~+ m
        double raise = salary * byPercent / 100;
/ v  b* T7 Q) t- o. c# w        salary += raise;
& }" r5 W* n* g8 O. l    }
2 j( @/ K4 z6 ?0 z! x! K; X    public String toString() {
0 A3 w& V4 X  V  P        return getClass().getName() + "[name=" + name + ",salary=" + salary
" @/ f" e, A, g! }+ k" X* k! S' L" p( C) Q                + ",hireDay=" + hireDay + "]";
; I  b- J$ P' D. ?5 ^( N0 x    }, _5 I/ k, t# p5 {4 s7 l
    private String name;
8 t. Q' H' u% R1 P7 ]( E  S    private double salary;
' [% h1 h" F! n7 ~    private Date hireDay;, M/ u; X- l2 \* k0 {
}! k8 w5 N+ T" [- A5 {4 o; L3 ~
  结果是没有向文件写入任何数据,为什么呢?2 n' D1 M2 f4 p4 m
  唯一的错误就在main方法中没有调用out.close(),把数据从缓冲区刷新到文件。因此用完资源即时关闭是很重要的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-5 23:42 , Processed in 0.188319 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表