Entradas e Saídas em Java: Difference between revisions
From Wiki**3
No edit summary |
No edit summary |
||
| (31 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
{{NAVPO}} | |||
{{TOCright}} | |||
Em Java, tal como noutras linguagens, os mecanismos de entradas e saídas desempenham um papel crucial na manipulação de dados. A classe '''File''' é um dos pilares dessa interação, servindo como uma ponte entre o código e os ficheiros no sistema. Para um fluxo mais refinado de dados, existem os conceitos '''InputStream''' e '''OutputStream''', por um lado, e '''Reader''' e '''Writer''', por outro, que facilitam a leitura e escrita de informação sob várias formas. A composição de canais amplia ainda mais as possibilidades de manipulação de dados. Para estes casos, os padrões de desenho Decorator e Adapter fornecem a estruturação de base. | |||
[[category:PO | Existem várias formas pré-definidas de acesso a ficheiros, podendo ser desenvolvidas outras. Uma característica interessante é o acesso aleatório a ficheiros, que permite uma interação não sequencial com os dados persistentes. A serialização, por sua vez, é fundamental para a conversão de tipos primitivos e objectos em formatos armazenáveis, com a interface '''Serializable''' desempenhando um papel central. A serialização em Java, através desta interface, é completamente automática. No entanto, como nem tudo é necessariamente serializável, existe a palavra-chave '''transient''' para controlar o processo de serialização. Note-se que este processo, apesar de automático e conveniente, tem alguns problemas sérios em alguns contextos. Ver o manual (endereço abaixo). | ||
O controlo de problemas relacionados com entradas e saídas em Java é realizado primariamente via tratamento de excepções. As excepções específicas destas operações são subclasses de '''IOException''' (embora possam ocorrer outras, específicas de certas operações). | |||
O manual de Java apresenta uma introdução à ''package'' '''java.io''', onde estão organizados estes e outros conceitos. | |||
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/package-summary.html | |||
= Nota sobre ordenação de texto em língua natural = | |||
== O "problema" do texto em língua natural == | |||
Embora não directamente relacionado com o tópico de entradas e saídas, o processamento de texto pode implicar ordenação de texto em língua natural. | |||
Se forem usados os processos meramente relacionados com a codificação de caracteres, listas de nomes com acentos podem ser ordenadas de forma errónea: | |||
Análise e Síntese de Algoritmos | |||
Compiladores | |||
Cálculo I | |||
Álgebra | |||
A ordem correcta seria: | |||
Álgebra | |||
Análise e Síntese de Algoritmos | |||
Cálculo I | |||
Compiladores | |||
A resolução do problema passa pela utilização dos conceitos relacionados com texto e sensíveis às definições de localização (região e língua natural) e não meramente com codificação de caracteres. No caso concreto deste exemplo, usa-se um comparador especial, '''Collator''', parametrizado com uma instância de '''Locale''' (define a forma de ordenação para uma dada língua natural): | |||
{{CollapsedCode|Collator & Locale|<source lang="java"> | |||
import java.text.Collator; | |||
import java.util.Locale; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
public class App { | |||
public static void main(String[] main) { | |||
ArrayList<String> l = new ArrayList<>(); | |||
l.add("Análise e Síntese de Algoritmos"); | |||
l.add("Compiladores"); | |||
l.add("Cálculo I"); | |||
l.add("Álgebra"); | |||
Collections.sort(l, Collator.getInstance(Locale.getDefault())); | |||
System.out.println(l); | |||
} | |||
} | |||
</source> | |||
}} | |||
== Collators serializáveis == | |||
Se o objecto que usa o Collator implementar Serializable, pode ocorrer um problema: Collator não implementa Serializable. Uma solução passa por definir um wrapper que é serializável e que reinicializa o Collator quando lido de disco. | |||
{{CollapsedCode|CollatorWrapper.java|<source lang="java"> | |||
import java.text.Collator; | |||
import java.util.Comparator; | |||
import java.util.Locale; | |||
import java.io.Serializable; | |||
import java.io.IOException; | |||
import java.io.ObjectInputStream; | |||
class CollatorWrapper implements Comparator<String>, Serializable { | |||
private static final long serialVersionUID = 202110251850L; | |||
private transient Collator _collator = Collator.getInstance(Locale.getDefault()); | |||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { | |||
ois.defaultReadObject(); | |||
_collator = Collator.getInstance(Locale.getDefault()); | |||
} | |||
@Override | |||
public int compare(String s1, String s2) { return _collator.compare(s1, s2); } | |||
} | |||
</source> | |||
}} | |||
Exemplo de aplicação que usa o wrapper. | |||
{{CollapsedCode|App.java|<source lang="java"> | |||
import java.util.Set; | |||
import java.util.TreeSet; | |||
import java.io.BufferedInputStream; | |||
import java.io.BufferedOutputStream; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.ObjectInputStream; | |||
import java.io.ObjectOutputStream; | |||
public class App { | |||
public static void main(String[] main) { | |||
Set<String> set = new TreeSet<>(new CollatorWrapper()); | |||
// add first two elements | |||
set.add("Análise e Síntese de Algoritmos"); | |||
set.add("Compiladores"); | |||
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("set.dat")))) { | |||
oos.writeObject(set); | |||
} | |||
catch (IOException e) { e.printStackTrace(); } | |||
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("set.dat")))) { | |||
set = (Set<String>)ois.readObject(); | |||
} | |||
catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } | |||
// add more elements | |||
set.add("Cálculo I"); | |||
set.add("Álgebra"); | |||
System.out.println(set); | |||
} | |||
} | |||
</source> | |||
}} | |||
= Exemplos e Exercícios = | |||
== Exemplos == | |||
* [[Entradas e Saídas em Java/Exemplo 01: Leitura e Escrita de Texto|Exemplo 01: Leitura e Escrita de Texto]] | |||
* [[Entradas e Saídas em Java/Exemplo 02: Ficheiros de Acesso Binário|Exemplo 02: Ficheiros de Acesso Binário]] | |||
* [[Entradas e Saídas em Java/Exemplo 03: Ficheiro de Acesso Aleatório|Exemplo 03: Ficheiro de Acesso Aleatório]] | |||
* [[Entradas e Saídas em Java/Exemplo 04: Serialização de Objectos|Exemplo 04: Serialização de Objectos]] - Zorg e Zog | |||
== Exercícios == | |||
* [[Entradas e Saídas em Java/Exercício 01: Leitura de Ficheiros de Texto|Exercício 01: Leitura de Ficheiros de Texto]] | |||
* [[Entradas e Saídas em Java/Exercício 02: Leitura de Ficheiro Binário|Exercício 02: Leitura de Ficheiro Binário]] | |||
* [[Entradas e Saídas em Java/Exercício 03: Serialização de Objectos|Exercício 03: Serialização de Objectos]] | |||
* [[Entradas e Saídas em Java/Exercício 04: Registo de Gatos|Exercício 04: Registo de Gatos]] | |||
[[category:Ensino]] | |||
[[category:PO]] | |||
Latest revision as of 09:22, 28 September 2023
Em Java, tal como noutras linguagens, os mecanismos de entradas e saídas desempenham um papel crucial na manipulação de dados. A classe File é um dos pilares dessa interação, servindo como uma ponte entre o código e os ficheiros no sistema. Para um fluxo mais refinado de dados, existem os conceitos InputStream e OutputStream, por um lado, e Reader e Writer, por outro, que facilitam a leitura e escrita de informação sob várias formas. A composição de canais amplia ainda mais as possibilidades de manipulação de dados. Para estes casos, os padrões de desenho Decorator e Adapter fornecem a estruturação de base.
Existem várias formas pré-definidas de acesso a ficheiros, podendo ser desenvolvidas outras. Uma característica interessante é o acesso aleatório a ficheiros, que permite uma interação não sequencial com os dados persistentes. A serialização, por sua vez, é fundamental para a conversão de tipos primitivos e objectos em formatos armazenáveis, com a interface Serializable desempenhando um papel central. A serialização em Java, através desta interface, é completamente automática. No entanto, como nem tudo é necessariamente serializável, existe a palavra-chave transient para controlar o processo de serialização. Note-se que este processo, apesar de automático e conveniente, tem alguns problemas sérios em alguns contextos. Ver o manual (endereço abaixo).
O controlo de problemas relacionados com entradas e saídas em Java é realizado primariamente via tratamento de excepções. As excepções específicas destas operações são subclasses de IOException (embora possam ocorrer outras, específicas de certas operações).
O manual de Java apresenta uma introdução à package java.io, onde estão organizados estes e outros conceitos. https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/package-summary.html
Nota sobre ordenação de texto em língua natural
O "problema" do texto em língua natural
Embora não directamente relacionado com o tópico de entradas e saídas, o processamento de texto pode implicar ordenação de texto em língua natural.
Se forem usados os processos meramente relacionados com a codificação de caracteres, listas de nomes com acentos podem ser ordenadas de forma errónea:
Análise e Síntese de Algoritmos Compiladores Cálculo I Álgebra
A ordem correcta seria:
Álgebra Análise e Síntese de Algoritmos Cálculo I Compiladores
A resolução do problema passa pela utilização dos conceitos relacionados com texto e sensíveis às definições de localização (região e língua natural) e não meramente com codificação de caracteres. No caso concreto deste exemplo, usa-se um comparador especial, Collator, parametrizado com uma instância de Locale (define a forma de ordenação para uma dada língua natural):
| Collator & Locale |
|---|
import java.text.Collator;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Collections;
public class App {
public static void main(String[] main) {
ArrayList<String> l = new ArrayList<>();
l.add("Análise e Síntese de Algoritmos");
l.add("Compiladores");
l.add("Cálculo I");
l.add("Álgebra");
Collections.sort(l, Collator.getInstance(Locale.getDefault()));
System.out.println(l);
}
}
|
Collators serializáveis
Se o objecto que usa o Collator implementar Serializable, pode ocorrer um problema: Collator não implementa Serializable. Uma solução passa por definir um wrapper que é serializável e que reinicializa o Collator quando lido de disco.
| CollatorWrapper.java |
|---|
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
class CollatorWrapper implements Comparator<String>, Serializable {
private static final long serialVersionUID = 202110251850L;
private transient Collator _collator = Collator.getInstance(Locale.getDefault());
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
_collator = Collator.getInstance(Locale.getDefault());
}
@Override
public int compare(String s1, String s2) { return _collator.compare(s1, s2); }
}
|
Exemplo de aplicação que usa o wrapper.
| App.java |
|---|
import java.util.Set;
import java.util.TreeSet;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class App {
public static void main(String[] main) {
Set<String> set = new TreeSet<>(new CollatorWrapper());
// add first two elements
set.add("Análise e Síntese de Algoritmos");
set.add("Compiladores");
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("set.dat")))) {
oos.writeObject(set);
}
catch (IOException e) { e.printStackTrace(); }
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("set.dat")))) {
set = (Set<String>)ois.readObject();
}
catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
// add more elements
set.add("Cálculo I");
set.add("Álgebra");
System.out.println(set);
}
}
|
Exemplos e Exercícios
Exemplos
- Exemplo 01: Leitura e Escrita de Texto
- Exemplo 02: Ficheiros de Acesso Binário
- Exemplo 03: Ficheiro de Acesso Aleatório
- Exemplo 04: Serialização de Objectos - Zorg e Zog