A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 逝去的记忆ヽ 于 2012-6-26 00:25 编辑

代码说问题:
class OutputStreamDemo
{
public static void main(String[] args) throws IOException
{
  methed_1();
  methed_2();//这里打印的是一排问号。那么我的问题是 通过第二种方法怎么能实现让汉字打印出来?

  methed_3();//这里用数组可以打印正常结果。
}
public static void methed_3()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  byte[] by = new byte[1024];//这个方法中,这里用了字节数组,直接开辟了大小为1024的空间,如果读取的字节数特别少的话,那么在内存中是不是很浪费呢?还有就是这里要是读取很大的数据时,要通过[1024*1024]来读取吗?是不是更浪费啊?在API有一个available()方法。都通过这个来读取数据和数组读取有什么差别?
  int num = 0;
  while ((num = fis.read(by))!= -1)
  {
   System.out.println(new String (by,0,num));
  }
}
public static void methed_2()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  
  int num = 0;
  while ((num = fis.read())!= -1)
  {
   System.out.println((char)num);
  }
}
public static void methed_1()throws IOException
{
  FileOutputStream fos = new FileOutputStream("OutputStreamDemo.txt");
  fos.write("这个真没有".getBytes());
  fos.close();
}
}

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

15 个回复

倒序浏览
methed_2( )  
FileInputStream fis = new FileInputStream("OutputStreamDemo.txt"); //字节流
System.out.println((char)num);转换成字符 会出错  用FileReader 或BufferedReader  
内存放 1024个字节还是不成问题的 一般都用 byte[] by = new byte[1024] 一k 或byte[] by = new byte[4096]一般硬盘存储单位,一簇   
回复 使用道具 举报
1. 这是字节流,字节流一般不会打印,操作文本数据一般用字符流:FileWriter&FileReader

2. System.out.println(new String (by,0,num));这里取到的数据并不是1024所有的数据,而是从0到num,刚刚好的大小,不会浪费

3. read()方法是按字节一个个读取,读一个写一个

4. read(byte[] b)是按字节数组循环读取,好比这里字节数组大小是1024,则每读1024字节数据就存储进缓冲区中,再将1024数据写入,接着执行下一个循环

5. available方法,可以免去循环读取数据,因为它是定义一个刚刚好大小的数组,比如你复制一张图片2兆,available就是2兆大小
回复 使用道具 举报

/*

/*FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  byte[] by = new byte[1024];//这个方法中,这里用了字节数组,直接开辟了大小为1024的空间,如果读取的字节数特别少的话,那么在内存中是不是很浪费呢?还有就是这里要是读取很大的数据时,要通过[1024*1024]来读取吗?是不是更浪费啊?在API有一个available()方法。都通过这个来读取数据和数组读取有什么差别?
  int num = 0;*/
FileInputStream是一个字节一个字节的读取的,所以才有了BufferedInputStream的出现,它内部封装了一个可变数组不用再自定义数组,这就是装饰类。
回复 使用道具 举报
byte[] by = new byte[1024];//这个方法中,这里用了字节数组,直接开辟了大小为1024的空间,如果读取的字节数特别少的话,那么在内存中是不是很浪费呢?还有就是这里要是读取很大的数据时,要通过[1024*1024]来读取吗?是不是更浪费啊?在API有一个available()方法。都通过这个来读取数据和数组读取有什么差别?//available()方法可以返回文件的具体大小,如果读取文件不是很大,用这个很好,如果文件特别大,超出了内存的范围,当创建数组时容易造成内存损坏,所以这个方法要慎用,所以还是用直接创建数组比较安全
回复 使用道具 举报
import java.io.*;


class OutputStreamDemo
{
public static void main(String[] args) throws IOException
{
  methed_1();
  methed_2();

  methed_3();//这里用数组可以打印正常结果。
}
public static void methed_3()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  byte[] by = new byte[1024];//一般都用 byte[] by = new byte[1024] 一k 或byte[] by = new byte[4096]一般硬盘存储单位,一簇   

  int num = 0;
  while ((num = fis.read(by))!= -1)
  {
   System.out.println(new String (by,0,num));//这里取到的数据并不是1024所有的数据,而是从0到num,刚刚好的大小,不会浪费
  }
}
public static void methed_2()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  
  int num = 0;
  while ((num = fis.read())!= -1)
  {
   System.out.println(num);//直接打印num问号问题解决
  }
}
public static void methed_1()throws IOException
{
  FileOutputStream fos = new FileOutputStream("OutputStreamDemo.txt");
  fos.write("这个真没有".getBytes());
  fos.close();
}
}
回复 使用道具 举报
李伟 中级黑马 2012-6-25 20:41:50
7#
methed_2();//这里打印的是一排问号。那么我的问题是 通过第二种方法怎么能实现让汉字打印出来?
public static void methed_2()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo1.txt");
  InputStreamReader isr=new InputStreamReader(fis,"gb2312");//用转换流的方式可以输出字符
  int num = 0;
  while ((num = isr.read())!= -1)
  {
   System.out.println((char)num);
  }
回复 使用道具 举报
王莹 中级黑马 2012-6-25 20:52:36
8#
代码说明问题
第一个方法
public static void methed_3()throws IOException
{
   FileInputStream fis = new FileInputStream("F:\\OutputStreamDemo.txt");
   //下面的方法中,用字节数组,直接开辟1024整数倍的空间,而available()方法可以定义了一个文件字节刚刚好的缓冲区,适用于数据不是很大的时候,比如MP3文件,小的视频等。开辟了1024的空间,就是每读1024个字节就打印,然后继续读后面的数据,满1024个字节再打印,其实只有一个数组by,数据再多也就这一个。而且1024个字节才1k,即使数据很小,不足1024个字节,也不会很浪费内存的。
   byte[] by = new byte[1024];
   int num = 0;
   while ((num = fis.read(by))!= -1)
   {
    System.out.println(new String (by,0,num));
   }
}
第二个方法我改成了这样:
public static void methed_2()throws IOException
{
   BufferedReader bufr = new BufferedReader(new FileReader("F:\\m.txt"));//因为你要输入的是中文,要用到字符流的FileReader
   String line=null;
   while((line=bufr.readLine())!=null)
  {
    System.out.println(line);
  }
}

下面是我运行程序的结果

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 周兴中 于 2012-6-25 21:44 编辑

public static void methed_2()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  
  int num = 0;
  while ((num = fis.read())!= -1)//FileInputStream的read()方法,每次只读取一个字节,读取的文字则是由两个字节组成,如果你一定想用这种方法输出中文,可以每读两个字符输出一次.方法其实等同于method_3中的定义字节数组,然后将读取到的字节写入数组的read(byte[] by)方法,  {
   System.out.println((char)num);
  }
}


可以改成以下代码:  其实以下代码抽取出来就相当于实现了 read(byte[] b)
public static void methed_2()throws IOException
{
  FileInputStream fis = new FileInputStream("OutputStreamDemo.txt");
  
  int num = 0;
  int x = 0;
  byte[] by = new byte[2];
  while ((num = fis.read())!= -1)
  {
         
          by[x] = (byte)num;
          if(x%2==1){
                  System.out.println(new String(by,0,2));
                          x = 0;
                          continue ;
          }
    x++;
  }
回复 使用道具 举报
问题一的回答: 看read返回的是什么,是字节,read是读取一个个字节的,而中文编码一个中文是2个字节(一个字符),那返回一个字节,怎么返回,拆成一半吗?所以返回一定是乱码,  我们读取中文字节,一般用FileReader类。

回复 使用道具 举报
先回答你第一个问题
read是一次读取一个字节的,而中文编码一个中文是2个字节(一个字符),所有是乱码

这就涉及到编码问题, 参数里能传入编码的流有InputStreamReader, 但是InputStreamReader 构造方法传入的另一个参数还必须是字节流,所有又必须用到字节流到字符流的转换问题.



我的代码,经过测试,完美通过


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

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

        methed_2();
    }

    public static void methed_2() throws IOException
    {
        FileInputStream fr = new FileInputStream("OutputStreamDemo.txt");

        InputStreamReader isr = new InputStreamReader(fr, "UTF-8");

        BufferedReader bufr = new BufferedReader(isr);

        String line = null;

        while ((line = bufr.readLine()) != null)
        {
            System.out.print(line);
        }

        bufr.close();
    }

}

因为InputStreamReader和BufferedReader 都继承自Reader,而BufferedReader 的构造器又是Reader.

Writer也是一样的处理

BufferedWriter oWriter = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8"));  









回复 使用道具 举报
王莹 发表于 2012-6-25 20:52
代码说明问题
第一个方法
public static void methed_3()throws IOException

你改后的第二方法在EditPlus中测试不能通过,但是在MyEclipse中测试能通过,我也不知道怎么会这样?
回复 使用道具 举报
严明 发表于 2012-6-25 23:01
你改后的第二方法在EditPlus中测试不能通过,但是在MyEclipse中测试能通过,我也不知道怎么会这样? ...

我就是在EditPlus中实验的呀,我读取的文件名和你的不一样,你要不再实验一下啊?
回复 使用道具 举报
王莹 发表于 2012-6-26 06:40
我就是在EditPlus中实验的呀,我读取的文件名和你的不一样,你要不再实验一下啊? ...

我传到论坛中的代码一般都会用两种编译工具来测试一下,问题不是文件名是不是一样, 我按你的文件名用记事本和VIM分别建立同一个文件,但是用EditPlus来测试还是出现乱码,这我也无法解释!
但我的代码用两种测试工具都能通过,声明我并不怀疑你的代码的正确性.
回复 使用道具 举报
楼上的兄弟的,为了让你验证一下,我把我程序完整的代码贴过来。你可以看看能不能运行出来。

import java.io.*;
class TransStream
{
public static void main(String[] args) throws IOException
{
   methed_1();
   methed_2();//这里打印的是一排问号。那么我的问题是 通过第二种方法怎么能实现让汉字打印出来?
  methed_3();//这里用数组可以打印正常结果。
}

public static void methed_3()throws IOException
{
   FileInputStream fis = new FileInputStream("F:\\OutputStreamDemo.txt");
   byte[] by = new byte[1024];//这个方法中,这里用了字节数组,直接开辟了大小为1024的空间,如果读取的字节数特别少的话,那么在内存中是不是很浪费呢?还有就是这里要是读取很大的数据时,要通过[1024*1024]来读取吗?是不是更浪费啊?在API有一个available()方法。都通过这个来读取数据和数组读取有什么差别?
   int num = 0;
   while ((num = fis.read(by))!= -1)
   {
    System.out.println(new String (by,0,num));
   }
}

public static void methed_2()throws IOException
{
  
   BufferedReader bufr = new BufferedReader(new FileReader("F:\\m.txt"));
   String line=null;
   while((line=bufr.readLine())!=null)
  {
    System.out.println(line);
  }
}

public static void methed_1()throws IOException
{
   FileOutputStream fos = new FileOutputStream("F:\\OutputStreamDemo.txt");
   fos.write("这个真没有".getBytes());
   fos.close();
}
}


我就改了第二个方法,别的都是用的他的代码,我在F:\\m.txt里存的中文就是“我不知道”。

然后运行结果就是:



回复 使用道具 举报
严明 发表于 2012-6-26 09:07
我传到论坛中的代码一般都会用两种编译工具来测试一下,问题不是文件名是不是一样, 我按你的文件名用记事 ...

下面有回复,你看一下~~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马