Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: tiedoston lukeminen muuttujaan

Sivun loppuun

Tumettaja [05.05.2009 15:51:10]

#

Tarkoituksenani on saada luettua minkä tahansa tiedoston (kuten esim. sovelluksen, kuvan yms.) lähdekoodi String-muuttujaan. Oman käsitykseni mukaan nämä yleiset käytetyt tavat kuten BufferedReader ja Scanner eivät sellaisenaan sovi tälläisten tiedostojen lukemiseen, vai olenko väärässä? Tätä String-muuttujaa pitäisi myös myöhemmin sitten hyödyntää siten, että muuttujasta voitaisiin suoraan luoda uusi tiedosto (joten kaikki tiedostossa oleva kama pitäisi säilyä muuttumattomana muuttujassa).

Eli, mitä tarvitsen jatkaakseni eteenpäin?

Metabolix [05.05.2009 17:22:04]

#

Oikea muoto binaaridatalle on byte-taulukko, ja sellaisen lukemiseen voi käyttää suoraan FileInputStream-luokkaa. Ainakin tämä koodi toimi täysin odotusten mukaan:

import java.io.*;
class koe {
  public static byte [] lue(String name) throws FileNotFoundException, IOException {
    File f = new File(name);
    byte [] buf = new byte[(int)f.length()];
    if (buf.length != 0) {
      FileInputStream fs = new FileInputStream(f);
      fs.read(buf);
      fs.close();
    }
    return buf;
  }
  public static void main(String [] args) {
    try {
      // luetaan lähdekoodi
      byte [] t = lue("koe.java");
      // muutetaan se Stringiksi ja tulostetaan
      System.out.print(new String(t));
    } catch (Exception e) {
    }
  }
}

Esimerkki on tietysti sinänsä huono, että se ei demonstroi, miksi String on datalle väärä muoto. Syy on tietenkin siinä, että String sisältää merkkejä eli tekstiä, joka on myös tietyn merkistökoodauksen mukaan tulkittu, kun taas binaaritiedostot sisältävät tavuja, joiden arvoista ei voi kiistellä.

Tumettaja [05.05.2009 18:59:34]

#

Eli onko Javalla siis mahdotonta konvertoida Byte-taulukko String-muuttujaan ja takaisin niin, että taulukon arvo ei muutu miksikään? Itse yritin kikkailla UTF8-koodauksen kanssa mutta eipä tuottanut juurikaan tulosta:

byte [] t = lue("c:\\test.mp3");
String s = new String(t, 0, t.length, "UTF8");
//takaisin Byte-taulukoksi
// s.getBytes("UTF8");

Metabolix [05.05.2009 19:24:12]

#

UTF-8:n ongelma on siinä, että kaikki mahdolliset tavuyhdistelmät eivät tuota kelvollisia merkkejä, jolloin Java heittää aiheesta ilmoituksen. ISO-8859-1 olisi ehkä mahdollinen enkoodaus, koska siinä yksi tavu vastaa yhtä merkkiä. Kannattaa kuitenkin miettiä tarkkaan, onko tuolle muunnokselle jokin todellinen tarkoitus.

Tumettaja [05.05.2009 19:49:19]

#

ISO-8859-1 enkoodaus hoiti homman, kiitoksia vastauksistasi!

Jackal von ÖRF [05.05.2009 23:26:59]

#

Siitä ei ole mitään takeita, että jos tavujonon muuttaa suoraan tekstiksi millä tahansa enkoodauksella, että se olisi jälleen palautettavissa alkuperäiseksi tavujonoksi. Esimerkiksi 0x00-tavu ei tietääkseni ole kelvollinen merkki missään merkistössä. Jos binääridata välttämättä pitää muuntaa tekstiksi ja takaisin, niin yksi varma tapa on käyttää base64-enkoodausta.

Metabolix [06.05.2009 08:55:05]

#

Jackal von ÖRF kirjoitti:

Esimerkiksi 0x00-tavu ei tietääkseni ole kelvollinen merkki missään merkistössä.

Kelvollisuuden voi varmasti määritellä monella tavalla, mutta kyllä se ainakin ASCII-yhteensopivissa merkistöissä on null-merkki. Tämä siis koskee myös ISO-8859-1:tä ja UTF-8:aa.

Siitä huolimatta String-tyypin käyttö binaaridatan esittämiseen ei ole semanttisesti oikea ratkaisu vaan enemmän tai vähemmän purkkaviritys tai jonkinlainen riskialtis optimointi.

Jackal von ÖRF [06.05.2009 11:22:00]

#

Joissain kielissä, kuten C, null-merkki lopettaa merkkijonon. Samoin esim. monet tiedostojärjestelmät kieltävät null:n tiedostonimissä. Binääridatan liikutteleminen merkkijonona voi aiheuttaa outoja bugeja.

Kuten Metabolix sanoi, pahintahan tässä on, ettei se tuo ilmi ohjelmoijan tarkoitusta. Se rikkoo mm. yksinkertaisen suunnittelun sääntöjä: http://martinfowler.com/articles/designDead.html­#id21637


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta