web-dev-qa-db-fra.com

La taille du caractère en Java 2 octets n'est-elle pas?

J'ai utilisé RandomAccessFile pour lire une byte à partir d'un fichier texte.

public static void readFile(RandomAccessFile fr) {
    byte[] cbuff = new byte[1];
    fr.read(cbuff,0,1);
    System.out.println(new String(cbuff));
}

Pourquoi est-ce que je vois un personnage complet en train d'être lu?

43
Shrinath

Un char représente un caractère en Java (*). Il a une taille de 2 octets (du moins c'est ce que suggère la plage de valeurs valides).

Cela ne signifie pas nécessairement que chaque représentation d'un caractère est longue de 2 octets. En fait, de nombreux encodages ne réservent qu'un octet pour chaque caractère (ou utilisent un octet pour les caractères les plus courants).

Lorsque vous appelez le constructeur String(byte[]), vous demandez à Java de convertir le byte[] en String à l'aide du codage par défaut de la plate-forme. Comme le codage par défaut de la plate-forme est généralement un codage sur 1 octet tel que ISO-8859-1 ou un codage de longueur variable tel que UTF-8, il peut facilement convertir ce 1 octet en un seul caractère.

Si vous exécutez ce code sur une plate-forme qui utilise UTF-16 (ou UTF-32 ou UCS-2 ou UCS-4 ou ...) comme codage par défaut de la plate-forme, vous n'obtiendrez pas un résultat valide (vous obtiendrez String contenant le caractère de remplacement Unicode à la place).

C'est l'une des raisons pour lesquelles vous ne devriez pas dépendre du codage par défaut de la plate-forme: lors de la conversion entre byte[] et char[]String ou entre InputStream et Reader ou entre OutputStream et Writer, vous devez toujours spécifier le codage que vous souhaitez utiliser. Sinon, votre code dépend de la plate-forme.

(*) ce n'est pas _/entièrement vrai: une char représente un codepoint UTF-16. Les codecs one ou two UTF-16 représentent des codages Unicode. Un point de code Unicode habituellement représente un caractère, mais parfois, plusieurs points de code Unicode sont utilisés pour constituer un seul caractère. Mais l’approximation ci-dessus est suffisamment proche pour permettre de discuter du sujet.

105
Joachim Sauer

Java stocke tous ses "caractères" en interne sous la forme de deux octets. Cependant, lorsqu'ils deviennent des chaînes, etc., le nombre d'octets dépend de votre codage.

Certains caractères (ASCII) sont à octet unique, mais beaucoup d’autres sont à octets multiples.

Java supporte Unicode, donc selon:

Documents de caractères Java

La valeur maximale prise en charge est "\ uFFFF" (hex FFFF, dec 65535) ou 11111111 11111111 binaire (deux octets).

13
Michael

Le constructeur String(byte[] bytes) prend les octets dans la mémoire tampon et les code en caractères.

Il utilise le jeu de caractères par défaut de la plateforme pour encoder des octets en caractères. Si vous le savez, votre fichier contient du texte codé dans un jeu de caractères différent, vous pouvez utiliser la fonction String(byte[] bytes, String charsetName) pour utiliser le codage correct (des octets aux caractères).

6
Andreas_D

Dans le fichier texte ASCII, chaque caractère ne représente qu'un octet.

1
RemoteSojourner

On dirait que votre fichier contient des caractères ASCII codés dans un octet seulement. Si le fichier texte contient des caractères non-ASCII, par ex. 2 octets UTF-8, alors vous obtenez uniquement le premier octet, pas le caractère entier.

1
andrew

Il y a quelques bonnes réponses ici mais je voulais préciser que jvm est libre de stocker une valeur de caractère dans tout espace de taille> = 2 octets.

Sur de nombreuses architectures, l'accès à la mémoire non alignée est pénalisé, de sorte qu'un caractère peut facilement être complété sur 4 octets. Un caractère volatile peut même être ajouté à la taille de la ligne de cache du processeur pour empêcher tout faux partage. https://en.wikipedia.org/wiki/False_sharing

Il peut être non intuitif pour les nouveaux programmeurs Java qu'un tableau de caractères ou une chaîne ne sont PAS simplement plusieurs caractères. Vous devriez apprendre et penser les chaînes et les tableaux distinctement de "plusieurs caractères". 

Je tiens également à souligner que les caractères Java sont souvent mal utilisés. Les gens ne réalisent pas qu'ils écrivent un code qui ne gérera pas correctement les points de code de plus de 16 bits.

1
William Deans

Java attribue 2 caractères sur 2 au caractère suivant UTF-16. Il occupe au minimum 2 octets lors de l’enregistrement d’un caractère et au maximum 4 octets. Il n'y a pas de 1 octet ou 3 octets de stockage pour le caractère.

0
Siva