2014-02-15 3 views
0

저는 워드 프로세서로 만들려고합니다. 나는 JFileChooser의 개념에 익숙해지고 그것을 내 코드에 구현했습니다. 내 희망은 JFileChooser를 사용하여 텍스트 파일을 열고 텍스트 파일의 내용을 JTextArea에 추가하는 것입니다. 나의 기능을 분리하는데 최선을 다하기 위해 MVC (model view controller)를 구현하여 3 개의 클래스를 갖췄다. 뷰는 WordFrame.java라고 불리며, 모델은 DataStuff.java이고 컨트롤러는 ProcessEvents.java입니다. 내 문제는 오히려 간단합니다. 텍스트 파일의 내용을 콘솔에 인쇄 할 수 있지만 TextArea에 해당 내용을 추가하려고하면 공백이 생깁니다. 아래 이미지는 문자 간격을 나타내는 textArea의 위치를 ​​보여줍니다. , 파일이로드 된 후입니다. 명시된 바와 같이 콘솔은 그것을 완벽하게 출력합니다.StringBuilder를 JTextArea에 추가합니다.

enter image description here

또한, 여기에 모델과 컨트롤러 여기

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.File; 
import java.util.Scanner; 


public class ProcessEvents { 

    private WordFrame frame = new WordFrame(); 
    private DataStuff data = new DataStuff(); 
    private DialogBoxes dialogs = new DialogBoxes(); 
    private boolean fileSaved; 
    String fileName = ""; 
    int fontSize = 0; 
    public ProcessEvents(WordFrame frame, DataStuff data){ 
     this.frame = frame; 
     this.data = data; 
     this.frame.addListener(new wordProcessListener()); 
    } 
    class wordProcessListener implements ActionListener{ 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if(e.getSource().equals(frame.openMenuItem)){ 
       frame.fileChooser.showOpenDialog(frame); 
       File f = frame.fileChooser.getSelectedFile(); 

       System.out.println("Command Executed: open"); 

       data.loadFile(f.getAbsoluteFile()); 

       if(data.showText() != null){ 
        String texts = data.showText().toString(); 

        System.out.println(data.showText()); 

        frame.textArea.append(data.showText().toString()); 
       } 
      } 
      if(e.getSource().equals(frame.FontMenuItem)){ 
       System.out.println("font"); 
      } 
      if(e.getSource().equals(frame.exitMenuItem)){ 
       dialogs.getConfirmDialog("exitWithoutSave"); 
      } 

      if(e.getSource().equals(frame.saveMenuItem)){ 
       dialogs.getSaveFileDialog(); 
       data.saveFile("Bingo"); 
       fileSaved = true; 
      } 
      if(e.getSource().equals(dialogs.close)){ 
       if(!fileSaved){ 

       } 
      } 
     } 

    } 
} 

에 대한 코드는 모델

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 

public class DataStuff { 
    private String fileName = ""; 
    private File file; 

    String text; 
    String name; 
    private File saveFile; 
    int counter = 0; 
    FileInputStream fis = null; 
    FileOutputStream fout = null; 
    StringBuilder sb; 
    char[] charArray; 
    int count = 0; 
    public void loadFile(File fileName){ 
     this.file = fileName; 
     try{ 
      fis = new FileInputStream(file); 
      charArray = new char[fis.read()]; 
      while ((counter = fis.read()) != -1) { 

       System.out.print((char) counter); 
       sb = new StringBuilder(); 
       sb.append(charArray); 

      } 

     } 
     catch(IOException ex){ 
      ex.printStackTrace(); 
     } 
     finally { 
      try { 
       if (fis != null) 
        fis.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
    public StringBuilder showText(){ 

     return sb; 

    } 
    public void saveFile(String name) { 
     this.name = name; 
     try{ 
     fout = new FileOutputStream(saveFile+"/"+name+".txt"); 
     } 
     catch(IOException e){ 
      System.out.println("File failed to save or something went horribly wrong"); 
     } 
    } 
} 

하고 항상 도움을 항상 감사입니다.

편집 : 그래서 아래 사람의 도움으로이 해결책을 고쳤습니다. 다른 사람이 같은 문제에 걸려서 차이를 볼 수있는 경우 위의 코드를 대체하고 싶지 않다고 결정했습니다. 뷰 클래스를 다시 조정합니다. 각 루프 반복에 새 문자열 빌더를 작성하는 대신에 그것을 재사용하는 것처럼 보이는 첫 리뷰에서

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 

public class DataStuff { 
    private String fileName = ""; 
    private File file; 

    String text; 
    String name; 
    private File saveFile; 
    int counter = 0; 
    FileInputStream fis = null; 
    FileOutputStream fout = null; 
    StringBuilder sb = new StringBuilder(4096); 
    //char[] charArray = new char[4096]; 
    int count = 0; 
    public void loadFile(File fileName){ 
     this.file = fileName; 
     try{ 
      fis = new FileInputStream(file); 
     // charArray = Character.toChars(fis.read()); 
      while ((counter = fis.read()) != -1) { 

       System.out.print((char) counter); 

       sb.append((char) counter); 

      } 

     } 
     catch(IOException ex){ 
      ex.printStackTrace(); 
     } 
     finally { 
      try { 
       if (fis != null) 
        fis.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
    public StringBuilder showText(){ 

     return sb; 

    } 
    public void saveFile(String name) { 
     this.name = name; 
     try{ 
     fout = new FileOutputStream(saveFile+"/"+name+".txt"); 
     } 
     catch(IOException e){ 
      System.out.println("File failed to save or something went horribly wrong"); 
     } 
    } 
} 
+0

이 새로운 코드의 유일한 문제점은 성능 측면에서 좋은 aproach가 아닌 바이트 단위로 파일을 읽는 것입니다. 배열을 사용하면 디스크 액세스 횟수가 줄어들어 성능이 향상됩니다. – vbazaga86

+0

그래, 그 어딘가에 대해 읽었습니다, 내가 BufferedReader를 사용해야한다는 것을 믿습니다. 그 점을 살펴보고 고마워, 많이 감사하겠습니다. –

답변

2

. while 루프를 시작하기 전에 stringbuilder를 작성하고 각 반복마다 읽기 문자를 추가하기 만하면됩니다.

+0

당신은 또한'new char [fis.read()]로 파일의 처음 몇 바이트를 잃어 버리고있다. char 배열을 만들고 고정 된 크기 인 StringBuilder (보통 4096 또는 8192)를 만들어야합니다. – AngerClown

+0

오케이 와우, 두 가지 대단한 답변을 통해 AngerClown과 vbazaga86을 모두 사용할 수 있습니다. 변경 사항을 보여주기 위해 위의 코드를 조정할 것입니다.하지만 작동하도록했습니다. 그러나 실제로 char 필드가 전혀 필요하지 않은 것으로 나타났습니다. 단순히 카운터의 int 값을 char로 캐스팅하고 추가했습니다. AngerClown이 제안한 고정 크기로 지정된 StringBuilder 그렇게 말하면서, 내 해결책을 들여다 보아라. 그리고 어떤 결함이라도 지적해라, 나는 그것을 많이 감사 할 것이다. –