前提・実現したいこと
文字列の中から「全角英数→半角英数」「半角カナ→全角カナ」をしたいです。
Java標準のNormalizer、またはicu4jを使えばいいかなと思っていましたが、微妙に望む形と違うので困っています。
他の方法でも「全角英数→半角英数」「半角カナ→全角カナ」が同時に実現できればなんでもいいです。
発生している問題・エラーメッセージ
「特定の文字種だけ全角、半角」にするのがうまくいかない
理想
アガパ 012 ABC ㈱
→アガパ 012 ABC ㈱
クラス | 処理 | 結果 | 問題 |
---|---|---|---|
java.text.Normalizer | normalize(str, Normalizer.Form.NFKC) | アガパ 012 ABC (株) | 記号等が変換される |
com.ibm.icu.text.Transliterator | getInstance("Halfwidth-Fullwidth").transliterate(str) | アガパ 012 ABC ㈱ | カナが半角になる |
com.ibm.icu.text.Transliterator | getInstance("Fullwidth-Halfwidth").transliterate(str) | アガパ 012 ABC ㈱ | 英数が全部半角になってしまうし、記号等の意図しない文字も変換される |
com.ibm.icu.text.Transliterator | getInstance("[:Katakana:];Halfwidth-Fullwidth").transliterate(str) | アガパ 012 ABC ㈱ | 半角濁点や半角半濁点が変換されない |
補足情報(FW/ツールのバージョンなど)
Java8
icu4j 66.1
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
こんなのでも宜しければ...
java
1import java.text.Normalizer; 2import java.util.regex.*; 3 4public class Main { 5 public static void main(String[] args) { 6 String s = "アガパ 012 ABC ㈱"; 7 Pattern p = Pattern.compile("([ヲ-゚A-Za-z0-9]+)"); 8 Matcher m = p.matcher(s); 9 StringBuffer sb = new StringBuffer(); 10 while(m.find()) { 11 m.appendReplacement(sb, Normalizer.normalize(m.group(), Normalizer.Form.NFKD)); 12 } 13 System.out.println(m.appendTail(sb)); 14 } 15}
投稿2020/03/30 14:29
編集2020/03/30 14:45総合スコア13209
0
java.text.Normalizer
Normalizer.normalize()を半角カタカナの範囲に適用。仕様に応じて範囲を変えてください。
Java
1import java.text.Normalizer; 2import java.util.function.Function; 3import java.util.function.IntUnaryOperator; 4import java.util.stream.Collectors; 5 6public class WidthConversion { 7 8 static IntUnaryOperator anFull2Half = c -> ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z') ? c + ('A' - 'A') : ('0' <= c && c <= '9') ? c + ('0' - '0') : c; 9 static Function<String,String> kHalf2Full = s -> (s.compareTo("。") >= 0 && s.compareTo("゚") <= 0) ? Normalizer.normalize(s, Normalizer.Form.NFKC) : s; 10 static Function<String, String> convert = s -> s.chars().map(anFull2Half).mapToObj(c -> String.valueOf((char) c)).map(kHalf2Full).collect(Collectors.joining()); 11 12 static void test(Function<String, String> f, String source) { 13 System.out.println(f.apply(source)); 14 } 15 16 public static void main(String[] args) { 17 test(convert,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); 18 test(convert,"アイウエオァィゥェォカキクケコガギグゲゴサシスセソザジズゼゾタチツテトダヂヅデドナニヌネノハヒフヘホバビブベボパピプペポマミムメモヤユヨラリルレロワヲン゙゚ッャュョーヴ。、「」"); 19 } 20 21}
NKFC機能版
Java
1 static Function<String,String> partiallyConvert = 2 s -> (s.compareTo("A") >= 0 && s.compareTo("Z") <= 0 || 3 s.compareTo("a") >= 0 && s.compareTo("z") <= 0 || 4 s.compareTo("0") >= 0 && s.compareTo("9") <= 0 || 5 s.compareTo("。") >= 0 && s.compareTo("゚") <= 0) 6 ? Normalizer.normalize(s, Normalizer.Form.NFKC) : s; 7 8 // NFKC機能を有効にするには、半角カタカナを1文字づつ処理してはならない。 9 // 濁点、半濁点をそれが修飾する文字とセットにする。 10 static BiConsumer<LinkedList<String>,String> withConsonantMark = 11 (a,s) -> { 12 if (!a.isEmpty() && ("゙".equals(s) || "゚".equals(s))) 13 a.add(a.removeLast() + s); 14 else 15 a.add(s); 16 }; 17 18 static Function<String, String> convert = 19 s -> s.chars() 20 .mapToObj(c -> String.valueOf((char) c)) 21 .collect(LinkedList<String>::new, withConsonantMark, List::addAll) 22 .stream() 23 .map(partiallyConvert) 24 .collect(Collectors.joining());
partiallyConvert
はjimbeさんの正規表現に近くなりました。
投稿2020/03/30 14:01
編集2020/03/31 06:24総合スコア1090
0
作ってみました。
class HanZen { final static char[] ktab = ("ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテト" + "ナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン").toCharArray(); final static char[] ptab = ("................111111111111111.....22222...............").toCharArray(); public static String conv(String s) { int n = s.length(), j = 0; char p = 0, t[] = new char[n]; for (int i = 0; i < n; i++) { char c = s.charAt(i); if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { t[j++] = (char)(c - ('A' - 'A')); p = 0; } else if (c >= 'ヲ' && c <= 'ン') { t[j++] = ktab[c-'ヲ']; p = ptab[c-'ヲ']; } else if (c == '゙' && p >= '1') { t[--j] = (char)(t[j++] + 1); p = 0; } else if (c == '゚' && p == '2') { t[--j] = (char)(t[j++] + 2); p = 0; } else { t[j++] = c; p = 0; } } return new String(t, 0, j); } } class Main { public static void main(String[] args) { String s = "abc,abc. はばぱ、ハバパ。"; System.out.println(s); System.out.println(HanZen.conv(s)); } }
追記
全角数字の変換が抜けていました。
if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
を
if (c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9') {
に修正してください。
投稿2020/03/30 10:30
編集2020/03/30 14:48総合スコア8224
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
万能薬はなかなかない。ルールが独特ならシコシコやるしかないとおもいます。
java
1import java.util.Arrays; 2public class Hoge { 3 private static final String[][] table = { 4 {"ア", "ア"}, 5 {"イ", "イ"}, 6 {"ガ", "ガ"}, 7 {"ネ", "ネ"}, 8 {"ン", "ン"}, 9 }; 10 private static String conv(final String input) { 11 return 12 Arrays.stream(table) 13 .reduce( 14 input, 15 (text, t) -> text.replace(t[0], t[1]), 16 (a, b) -> null); 17 } 18 public static void main(final String[] argss) { 19 final String input = "アガネイロ"; 20 final String out = conv(input); 21 System.out.println(String.format("%s -> %s", input, out)); 22 } 23} 24// アガネイロ -> アガネイロ
投稿2020/03/30 07:02
編集2020/03/30 08:13総合スコア4061
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/03/30 07:04
2020/03/30 07:09
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/03/31 00:07
2020/03/31 03:48