質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

3065閲覧

環境依存文字のパリーデーションを理解したい

k499778

総合スコア599

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2020/03/09 06:33

環境依存文字のバリデーションを理解したいのですが、以下のコードを理解したいです。ポイントやどこを理解したらわかりやすいでしょうか?

java

1package xxx.validator; 2 3import java.nio.charset.Charset; 4import java.nio.charset.CharsetEncoder; 5import java.util.ArrayList; 6import java.util.List; 7 8import javax.faces.FacesException; 9import javax.faces.application.FacesMessage; 10import javax.faces.component.UIComponent; 11import javax.faces.context.FacesContext; 12import javax.faces.internal.FacesMessageUtil; 13import javax.faces.internal.UIComponentUtil; 14import javax.faces.validator.Validator; 15 16import org.apache.commons.lang.StringUtils; 17import org.seasar.framework.util.AssertionUtil; 18import org.seasar.framework.util.StringUtil; 19import org.seasar.teeda.extension.exception.ExtendValidatorException; 20import org.seasar.teeda.extension.util.TargetCommandUtil; 21import org.seasar.teeda.extension.validator.ValidationTargetSelectable; 22 23public class InvalidCharsetValidator implements Validator, ValidationTargetSelectable { 24 25 public static final String INVALID_CHARSET_MESSAGE_ID = "xxx"; 26 27 private String target; 28 29 private String[] targets; 30 31 private String messageId; 32 33 private String charSet; 34 35 private List<String> invalidCharList; 36 37 @Override 38 public void validate(FacesContext context, UIComponent component, Object value) throws FacesException { 39 AssertionUtil.assertNotNull("context", context); 40 AssertionUtil.assertNotNull("component", component); 41 42 if (!isTargetCommandValidation(context, targets)) { 43 return; 44 } 45 46 if (value == null) { 47 return; 48 } 49 50 if (hasInvalidCharset(value)) { 51 Object[] args = new Object[] { UIComponentUtil.getLabel(component), 52 StringUtils.join(invalidCharList.toArray(new String[0]), ",") }; 53 String msgId = (getMessageId() != null) ? getMessageId() : INVALID_CHARSET_MESSAGE_ID; 54 FacesMessage message = FacesMessageUtil.getMessage(context, msgId, args); 55 throw new ExtendValidatorException(message, new String[] { msgId }); 56 } 57 } 58 59 protected boolean hasInvalidCharset(Object value) { 60 if (value == null || !(value instanceof String)) { 61 return false; 62 } 63 64 String strValue = (String) value; 65 Charset charset = Charset.forName(charSet); // 文字セット(コード)の設定 66 CharsetEncoder encoder = charset.newEncoder(); // エンコーダーの生成 67 68 invalidCharList = new ArrayList<String>(); 69 for (int i = 0; strValue != null && i < strValue.length(); i++) { 70 char target_c = strValue.charAt(i); 71 72 // Unicodeマッピング不整合が発生する文字を事前に変換 73 target_c = convertMappingMismatchChar(target_c, charset); 74 75 // エンコード可能かどうかを1文字づつチェック 76 if (!encoder.canEncode(target_c)) { 77 78 if (Character.isHighSurrogate(target_c)) { 79 // サロゲートペアの場合 80 char[] invalidChars = Character.toChars(Character.toCodePoint(target_c, strValue.charAt(i + 1))); 81 addInvalidCharList(new String(invalidChars)); 82 i++; 83 } else { 84 // サロゲートペアではない場合 85 addInvalidCharList(new Character(target_c).toString()); 86 } 87 88 } 89 } 90 return invalidCharList.size() > 0; 91 } 92 93 /** 94 * Unicodeマッピング不整合が発生する特殊文字の変換 95 * 入力値を EUC_JP または Shift_JIS として扱う場合にUnicodeマッピング不整合が発生する文字を個別に変換して回避するため変換を行う 96 * 以下の文字を変換の対象としている 97 * ¢(0xFFE0) 98 * £(0xFFE1) 99 * ¬(0xFFE2) 100 * ∥(0x2225) 101 * -(0xFF0D) 102 * ~(0xFF5E) 103 * ―(0x2015) 104 * @param target_c 対象文字 105 * @return 変換後文字 106 */ 107 private char convertMappingMismatchChar(char target_c, Charset charset) { 108 if (StringUtils.equals("EUC-JP", charset.name()) || StringUtils.equals("Shift_JIS", charset.name())) { 109 switch (target_c) { 110 case (char) 0xFFE0: 111 target_c = (char) 0x00A2; 112 break; 113 case (char) 0xFFE1: 114 target_c = (char) 0x00A3; 115 break; 116 case (char) 0xFFE2: 117 target_c = (char) 0x00AC; 118 break; 119 case (char) 0x2225: 120 target_c = (char) 0x2016; 121 break; 122 case (char) 0xFF0D: 123 target_c = (char) 0x2212; 124 break; 125 case (char) 0xFF5E: 126 target_c = (char) 0x301C; 127 break; 128 case (char) 0x2015: 129 target_c = (char) 0x2014; 130 break; 131 default: 132 break; 133 } 134 } 135 return target_c; 136 } 137 138 protected void addInvalidCharList(String str) { 139 invalidCharList.add("\"" + str + "\""); 140 } 141 142 public String getMessageId() { 143 return !StringUtil.isEmpty(messageId) ? messageId : INVALID_CHARSET_MESSAGE_ID; 144 } 145 146 public void setMessageId(String messageId) { 147 this.messageId = messageId; 148 } 149 150 public String getCharSet() { 151 return charSet; 152 } 153 154 public void setCharSet(String charSet) { 155 this.charSet = charSet; 156 } 157 158 public List<String> getInvalidCharList() { 159 return invalidCharList; 160 } 161 162 public void setInvalidCharList(List<String> invalidCharList) { 163 this.invalidCharList = invalidCharList; 164 } 165 166 @Override 167 public String getTarget() { 168 return target; 169 } 170 171 @Override 172 public void setTarget(String target) { 173 this.target = target; 174 if (StringUtil.isEmpty(target)) { 175 return; 176 } 177 targets = StringUtil.split(target, ", "); 178 } 179 180 @Override 181 public boolean isTargetCommandValidation(FacesContext context, String[] targets) { 182 return TargetCommandUtil.isTargetCommand(context, targets); 183 } 184 185}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

基本的には1文字ずつ取り出して target_c = strValue.charAt(i);

変換先文字コード charSettarget_c が表現できるか見ています:
// エンコード可能かどうかを1文字づつチェック if (!encoder.canEncode(target_c)) {

ただし、Unicode では「サロゲートペア」といって、2文字(正確にはコードポイント)の組み合わせで1文字を表現することがあり、
ペアの最初の1文字でサロゲートペアか判定して
Character.isHighSurrogate(target_c)
サロゲートペアなら続きの文字と合わせて「変換できない文字リスト」に追加しています。

で、その前に、変換先文字コードが EUC-JP, Shift_JIS の場合に
Java で通常 変換できない記号を自前で別の文字として読み替えて、変換できることにしています:

// Unicodeマッピング不整合が発生する文字を事前に変換 target_c = convertMappingMismatchChar(target_c, charset);

最終的に変換できない文字リストが空ならバリデーションに合格する感じです。

投稿2020/03/10 10:30

criticabug

総合スコア71

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問