Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Проблема с FileOutputStream


Автор: check 13.9.2006, 19:46
Метод open открывает файл и выводит его в текстовое поле, где его можно отредактировать. 
Метод save должен сохранить отредактированный текст в тот же файл.
Однако при нажатии кнопки "сохранить" выдается FileNotFoundException, хотя путь к файлу в FileInputStream передается правильный.
Если передать в FileInputStream произвольное имя файла, какой-нибудь 1.txt, сохраняется без проблем.
Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;

public class choos extends JFrame
{
   JTextArea txt;
   File currentFile;

   choos() {

     setSize(585,482);
     Container c = getContentPane();
     JPanel base = new JPanel();
     JPanel p1   = new JPanel();
     JPanel p2   = new JPanel();
     JButton b1 = new JButton("Открыть");
     JButton b2 = new JButton("Сохранить");
     p1.add(b1);
     p1.add(b2);
     base.add(p1);
     txt = new JTextArea(25,50);
     JScrollPane scrl = new JScrollPane(txt, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 

JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
     p2.add(scrl);
     base.add(p2);
     c.add(base);

     b1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            open();
         }
     });

     b2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            save();
         }
     });
    
WindowListener wndCloser = new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);


     setVisible(true);
   }

  public void open() {

    JFileChooser fc = new JFileChooser();
    ExtFileFilter ff1 = new ExtFileFilter("txt", "*.txt — текстовые файлы");
    fc.addChoosableFileFilter(ff1);
    ExtFileFilter ff2 = new ExtFileFilter("doc", "*.doc — документы Word");
    fc.addChoosableFileFilter(ff2);
    if( fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
          File f = fc.getSelectedFile();
          currentFile = f;
          
          try
           {
              FileInputStream inF = new FileInputStream(currentFile);
              DataInputStream in = new DataInputStream(inF);
              String str;
              while ((str = in.readLine()) != null)
              txt.append(str+"\n");
              in.close();
           }
          catch(IOException ex)
           {
              ex.printStackTrace();
           } 
    }

  }

  public void save()  {

   //это для проверки
   JOptionPane.showMessageDialog(null, currentFile); //в currentFile содержится правильный путь к файлу
  
    try
     {
        DataOutputStream out = new DataOutputStream(new FileOutputStream(currentFile));
        out.writeChars(txt.getText());
        out.close();
     }
    catch(IOException ex)
     {
        ex.printStackTrace();
     }  
  }


   public static void main(String[] args) {
     new choos();
   }
}

Автор: LSD 13.9.2006, 20:40
Все нормально работает. Рассказывай подробней как запускаешь, что делаешь.

Автор: check 13.9.2006, 21:40
Цитата(LSD @  13.9.2006,  20:40 Найти цитируемый пост)
как запускаешь, что делаешь
Да в общем, всё как обычно. 
Компилю 
Код

javac choos.java

Запускаю
Код

java choos

Открываю диалог выбора файлов,  потом открываю какой-нибудь текстовый файлик,  редактирую его, нажимаю "сохранить".
Файл остается таким, какой был, а в консоль выдается ошибка.  
Вот в общем-то и всё...

Автор: Metal_Heart 14.9.2006, 09:53
Я посмотрел, правда убрал эти строки:
Код

    ExtFileFilter ff1 = new ExtFileFilter("txt", "*.txt — текстовые файлы");
    fc.addChoosableFileFilter(ff1);
    ExtFileFilter ff2 = new ExtFileFilter("doc", "*.doc — документы Word");
    fc.addChoosableFileFilter(ff2);

результат:
открывает, сохраняет, но дописывает ещё кучу всякого двоичного мусора.

вставил вывод отладочной инфо:
в  open():
Код

System.out.println("длина до: "+txt.getText().length());

и в close():
Код

System.out.println("длина после: "+txt.getText().length());

добавив в исходный текстовик 1 символ получил следующее:
длина до: 9
длина после: 10

открыл заного:
длина до: 31

Как я поборол данную проблему:
1. очистка JTextArea в open():  txt.setText("");
2. в save(): вместо out.writeChars(txt.getText());
 подставил out.writeBytes(txt.getText());

Автор: LSD 14.9.2006, 10:21
Цитата(Metal_Heart @  14.9.2006,  10:53 Найти цитируемый пост)
открывает, сохраняет, но дописывает ещё кучу всякого двоичного мусора.

Это не мусор, он просто сохраняет файл в кодировке UTF-16BE.

Вот что написанно в JavaDoc по поводу данной ошибки:
Цитата
FileNotFoundException - if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason

вариант с директорией отпадает, остается нехватка прав на запись в данный файл. Проверь что у файла не стоит атрибут read-only и у пльзователя достаточно прав.

Автор: check 14.9.2006, 10:54
LSD,   да там стоял read-only.  smile   Что ж, "каждый человек имеет право на немного потупить".
Цитата(Metal_Heart @  14.9.2006,  09:53 Найти цитируемый пост)
1. очистка JTextArea в open():  txt.setText("");
2. в save(): вместо out.writeChars(txt.getText());
 подставил out.writeBytes(txt.getText());


Metal_Heart, помогло, спасибо.

 
Цитата(Metal_Heart @  14.9.2006,  09:53 Найти цитируемый пост)
ExtFileFilter ff2 = new ExtFileFilter("doc", "*.doc — документы Word");

Да, это я конечно погорячился.

Автор: Metal_Heart 14.9.2006, 12:54
Цитата(LSD @  14.9.2006,  10:21 Найти цитируемый пост)
Это не мусор, он просто сохраняет файл в кодировке UTF-16BE.


Это я понял, но ведь текстовому файлу этого не объяснишь!  smile

Добавлено @ 12:54 
Цитата(check @  14.9.2006,  10:54 Найти цитируемый пост)
Metal_Heart, помогло, спасибо.


Я очень рад! smile

Автор: MOFA 24.12.2006, 02:25
Та же проблема, FileNotFoundException при попытке создать FileOutputStream по заданому пути к файлу, хотя путь к файлу в передается правильный, я его вывожу для отладки. Если передать в FileOutputStream произвольное имя файла, какой-нибудь с:/1.txt, то файл создается без проблем, правда при попытке писать в него тоже генериться ексепшн.
Кусок кода такой:

Код

...

System.out.println(new PathUtil().getNotExistPath(imageFileName)); //todo: del

imageFile = new FileOutputStream(new PathUtil().getNotExistPath(imageFileName));

...


PathUtil().getNotExistPath(imageFileName) - возвращает полный путь к файлу, от корня, причем к еще не существующемо файлу.

Помогите пожалуйста, уже много дней ищу решение.

Автор: powerOn 24.12.2006, 02:56
1) Выложи стек-трейс исключения.
2) Приведи более подробный код (без new PathUtil().getNotExistPath(imageFileName), чтобы строки были хардкодные). 

Цитата(MOFA @  24.12.2006,  02:25 Найти цитируемый пост)
Если передать в FileOutputStream произвольное имя файла, какой-нибудь с:/1.txt, то файл создается без проблем, правда при попытке писать в него тоже генериться ексепшн.

а еще какое имя можно задать? .. кроме призвольного...

Автор: MOFA 24.12.2006, 03:04
Кстати, я дописал такие штуки:

Код

File imageF= new File(imageFileName);
if (!imageF.canWrite()) {
   System.out.println(imageF.getAbsolutePath());
}

java.lang.SecurityManager sm= new java.lang.SecurityManager();
sm.checkWrite(imageFileName);/**/

imageFile = new FileOutputStream(imageFileName);


Первая проверка выдает false, тоесть писать нельзя, вторая проверка выдает ccess denied (java.io.FilePermission obr/00.img write).
Причем, файл который я хочу создать и в него записать нигде до этого не открывался и путь на моей машине, а не на чужой, тоесть получается что у меня нету прав, как это можно исправить?

Автор: MOFA 24.12.2006, 14:12
Ну так что, кто-то знает в чем проблема и как ее решать?
Очень нужно, мож кто-то сталкивался, помогите пожалуйста.

Автор: powerOn 24.12.2006, 14:32
MOFA
Цитата(powerOn @  24.12.2006,  02:56 Найти цитируемый пост)
1) Выложи стек-трейс исключения.
2) Приведи более подробный код (без new PathUtil().getNotExistPath(imageFileName), чтобы строки были хардкодные). 

Цитата(MOFA @  24.12.2006,  02:25 Найти цитируемый пост)
Если передать в FileOutputStream произвольное имя файла, какой-нибудь с:/1.txt, то файл создается без проблем, правда при попытке писать в него тоже генериться ексепшн.

а еще какое имя можно задать? .. кроме призвольного...


Автор: MOFA 24.12.2006, 14:42
1) Трека как такового нету, выводит одну строку ексепшина
     например:
     file:\D:\__InstWorks\4_course\4_1\OPSSHI\my_course_work\project\classes\obr\00.img (Синтаксическая ошибка в имени файла, имени папки или метке тома)

2) Пример хардкорной строки : 
     file:/D:/__InstWorks/4_course/4_1/OPSSHI/my_course_work/project/classes/obr/00.img , такая какую показывает в ексепшине

3) Третий вопрос не понял, можно задавать любые имена, но при этом иногда файл создается, иногда нет, но не пишет в файл в любом случае.


Автор: powerOn 24.12.2006, 14:59
Цитата(MOFA @  24.12.2006,  14:42 Найти цитируемый пост)
1) Трека как такового нету, выводит одну строку ексепшина
     например:
     file:\D:\__InstWorks\4_course\4_1\OPSSHI\my_course_work\project\classes\obr\00.img (Синтаксическая ошибка в имени файла, имени папки или метке тома)

2) Пример хардкорной строки : 
     file:/D:/__InstWorks/4_course/4_1/OPSSHI/my_course_work/project/classes/obr/00.img , такая какую показывает в ексепшине

ты сам ответил на свой вопрос: Синтаксическая ошибка в имени файла, имени папки или метке тома.

Цитата(MOFA @  24.12.2006,  14:42 Найти цитируемый пост)
3) Третий вопрос не понял, можно задавать любые имена, но при этом иногда файл создается, иногда нет, но не пишет в файл в любом случае.

Имена задовать можно не все, а только те которые позволяет файловая система. Если файл не создается, то естественно записи никакой не будет. Иначе вопрос спорный. Если у тебя доступ к файловой системе только на чтение, то создать файл в ней никто не позволит, уж тем более писать в него.

Начни с формирования корректных имен файлов. 

Автор: MOFA 24.12.2006, 15:03
Может имеет смысл не указывать полный путь от корня, можно указать относительный путь, чтобы например создавалась папка рядом с приложением и потом в нее писались файлы, тогда у меня возникает вопрос, как это корректно сделать, можно пример?

И еще, насчет доступа, я же пишу на свою машину, какие тут могут быть проблемы, файл не ридонли, его изначально вообще не существует.

Добавлено @ 15:06 
И еще, если изменить например на такое:

Код

imageFile = new FileOutputStream(new PathUtil().getNotExistPath(imageFileName).substring(6));


то выводиться другой ексепшн:

D:\__InstWorks\4_course\4_1\OPSSHI\my_course_work\project\classes\obr\00.img (Системе не удается найти указанный путь)

Автор: powerOn 24.12.2006, 15:22
Цитата(MOFA @  24.12.2006,  15:03 Найти цитируемый пост)
Может имеет смысл не указывать полный путь от корня, можно указать относительный путь, чтобы например создавалась папка рядом с приложением и потом в нее писались файлы, тогда у меня возникает вопрос, как это корректно сделать, можно пример?

 1) Для абсолютного пути не нужно использовать префикс file:/. Достаточно C:/реальная папка/реальная папка/../ имя нового фала. Путь к файлу должен заранее существовать. Сам файл уже потом создается.
2) Можно создать файл  по относительному пути (например aaa/bbb/ccc.txt). Относительный путь начинается с рабочей директории, которая не обязательно совпадает с директорией в которой лежит исполняемый файл. 

Автор: MOFA 24.12.2006, 16:29
Спасибо за советы, вроде то что я хотел заработало, но возникла новая проблема, получается, что для создания файла, папка в которую мы хотим его создать должна заранее существовать, тоесть логично было бы ее создать при старте приложения, как это сделать?

Автор: powerOn 24.12.2006, 17:34
Код

File dir = new  File("C:/mydir/test");
dir.mkdirs();

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)