0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

全角半角変換と文字コード変換 — 日本語開発で避けられない文字処理の実践ガイド

0
Posted at

TL;DR

  • 全角/半角の不統一はバリデーションエラー、DB不整合、CSV取込失敗の原因になる
  • UTF-8/Shift_JIS/EUC-JPの文字コード混在が文字化けの根本原因
  • コードで自動化する方法と、手軽に確認できるオンラインツールを両方紹介する

全角・半角問題が発生する典型的なシーン

日本語を扱うシステム開発では、全角/半角の混在問題を避けて通れません。

// フォーム入力でよくある問題
const phone1 = "090-1234-5678";   // 半角(期待値)
const phone2 = "090ー1234ー5678"; // 全角(ユーザーが入力しがち)

// 同じ電話番号なのにバリデーションで弾かれる
/^\d{3}-\d{4}-\d{4}$/.test(phone1); // true
/^\d{3}-\d{4}-\d{4}$/.test(phone2); // false

実務でよく遭遇するケース:

シーン 問題 影響
フォームバリデーション 全角数字が正規表現にマッチしない ユーザー離脱
CSVインポート 半角カンマと全角カンマの混在 パース失敗
DB検索 WHERE name = '田中'で全角スペースを含む値がヒットしない データ欠損
API連携 JSON値に全角引用符"が混入 パースエラー
帳票出力 半角カタカナと全角カタカナの混在 見た目の不統一

JavaScriptで全角→半角変換を実装する

英数字の全角→半角変換

/**
 * 全角英数字を半角に変換する
 * Unicode上の全角英数字はU+FF01〜U+FF5Eに配置されており、
 * 対応する半角文字はU+0021〜U+007Eにある(差分: 0xFEE0)
 */
function toHankaku(str) {
  return str.replace(/[!-~]/g, (char) => {
    return String.fromCharCode(char.charCodeAt(0) - 0xFEE0);
  });
}

// テスト
console.log(toHankaku("ABC123"));
// => "ABC123"

console.log(toHankaku("Hello World!"));
// => "Hello World!"

全角スペース→半角スペース

function normalizeSpaces(str) {
  return str.replace(/\u3000/g, ' ');
}

console.log(normalizeSpaces("田中 太郎"));
// => "田中 太郎"

カタカナの半角→全角変換

半角カタカナは濁点・半濁点が別文字になるため、単純なコードポイント変換では対応できません。

const kanaMap = {
  'ガ': '', 'ギ': '', 'グ': '', 'ゲ': '', 'ゴ': '',
  'ザ': '', 'ジ': '', 'ズ': '', 'ゼ': '', 'ゾ': '',
  'ダ': '', 'ヂ': '', 'ヅ': '', 'デ': '', 'ド': '',
  'バ': '', 'ビ': '', 'ブ': '', 'ベ': '', 'ボ': '',
  'パ': '', 'ピ': '', 'プ': '', 'ペ': '', 'ポ': '',
  'ヴ': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', 'ソ': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '',
  '': '', '': '', '': '',
  '': '', '': '', '': '', '': '', '': '', '': ''
};

function hankakuKanaToZenkaku(str) {
  // 濁点・半濁点付きを先にマッチさせる(2文字→1文字)
  const sorted = Object.entries(kanaMap)
    .sort((a, b) => b[0].length - a[0].length);

  let result = str;
  for (const [hankaku, zenkaku] of sorted) {
    result = result.split(hankaku).join(zenkaku);
  }
  return result;
}

console.log(hankakuKanaToZenkaku("プログラミング"));
// => "プログラミング"

JavaScriptのNFKC正規化(簡易版)

Python同様、JavaScriptでもString.prototype.normalize('NFKC')が使えます(ES2015+)。多くのケースではこれだけで十分です。

// NFKC正規化: 全角英数字→半角、半角カタカナ→全角を一括変換
console.log("ABC123".normalize('NFKC'));
// => "ABC123"

console.log("プログラミング".normalize('NFKC'));
// => "プログラミング"

ただし「英数字だけ半角にしたいがカタカナはそのまま」のような選択的変換にはマッピングテーブルが必要です。

統合変換関数

function normalizeJapaneseText(str) {
  let result = str;
  // 1. 全角英数字→半角
  result = toHankaku(result);
  // 2. 半角カタカナ→全角
  result = hankakuKanaToZenkaku(result);
  // 3. 全角スペース→半角
  result = normalizeSpaces(result);
  return result;
}

console.log(normalizeJapaneseText("プログラミング school 2026"));
// => "プログラミング school 2026"

Pythonで全角→半角変換を実装する

Python 3にはunicodedataモジュールがあり、NFKCノーマライゼーションで一部の変換が可能です。

import unicodedata

def normalize_japanese(text: str) -> str:
    """NFKC正規化で全角英数字→半角、半角カタカナ→全角を一括変換"""
    return unicodedata.normalize('NFKC', text)

print(normalize_japanese("ABC123"))
# => "ABC123"

print(normalize_japanese("プログラミング"))
# => "プログラミング"

print(normalize_japanese("Hello World"))
# => "Hello World"  ※全角スペースも半角に変換される

PythonのNFKC正規化は多くのケースで十分ですが、「特定の文字だけ変換したい」(例: 英数字は半角にしたいがカタカナは全角のまま)場合はJavaScriptと同様にマッピングテーブルが必要です。

pandasでCSVデータの一括正規化

import pandas as pd
import unicodedata

df = pd.read_csv('customers.csv')

# 文字列カラムを一括正規化
str_columns = df.select_dtypes(include=['object']).columns
for col in str_columns:
    df[col] = df[col].apply(
        lambda x: unicodedata.normalize('NFKC', str(x)) if pd.notna(x) else x
    )

df.to_csv('customers_normalized.csv', index=False)

文字コードの基礎知識

UTF-8, Shift_JIS, EUC-JPの違い

文字コード 1文字のバイト数 主な用途 現在の推奨度
UTF-8 1-4バイト(可変長) Web標準、Linux、モダンなシステム全般 最推奨
Shift_JIS 1-2バイト Windows旧アプリ、CSV(Excel互換) レガシー用途のみ
EUC-JP 1-3バイト Unix/Linux旧システム ほぼ絶滅
ISO-2022-JP 1-2バイト(エスケープシーケンス) 日本語メール(RFC 2047) メールのみ

2026年現在、新規システムはUTF-8一択です。Shift_JISやEUC-JPは既存システムとの連携時にのみ使います。

文字化けが起きる仕組み

正しい表示:
  "日本語" → UTF-8: E6 97 A5 E6 9C AC E8 AA 9E → デコーダ(UTF-8) → "日本語" ✅

文字化け:
  "日本語" → UTF-8: E6 97 A5 E6 9C AC E8 AA 9E → デコーダ(Shift_JIS) → "譌・譛ャ隱枩" ❌

文字化けは「エンコードとデコードの文字コードが一致しない」ときに発生します。 ファイルを保存した文字コードと、開いたときに想定している文字コードが異なるだけです。

文字化けの特定と修復

よくある文字化けパターンから原因を推定できます。

表示 原因 修復方法
譌・譛ャ隱枩 UTF-8をShift_JISで開いた UTF-8で開き直す
æ¥æ¬èª UTF-8をLatin-1で開いた UTF-8で開き直す
��{�u�o(置換文字の連続) Shift_JISをUTF-8で開いた Shift_JISで開き直す
日本語 HTMLエンティティ デコードする

Node.jsでの文字コード変換

import iconv from 'iconv-lite';
import fs from 'node:fs';

// Shift_JIS → UTF-8
const sjisBuffer = fs.readFileSync('legacy_data.csv');
const utf8String = iconv.decode(sjisBuffer, 'Shift_JIS');

// UTF-8 → Shift_JIS(Excel向けCSV出力)
const sjisOutput = iconv.encode(utf8String, 'Shift_JIS');
fs.writeFileSync('for_excel.csv', sjisOutput);

Pythonでの文字コード変換

# Shift_JIS → UTF-8
with open('legacy_data.csv', 'r', encoding='shift_jis') as f:
    content = f.read()

with open('utf8_data.csv', 'w', encoding='utf-8') as f:
    f.write(content)

# 文字コード自動判定(chardetライブラリ)
import chardet

with open('unknown_encoding.csv', 'rb') as f:
    raw = f.read()
    detected = chardet.detect(raw)
    print(detected)
    # => {'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}

オンラインツールで手軽に変換・確認する

コードを書かずにブラウザで即座に確認したいケースも多いです。

  • DevToolBox 全角/半角変換: カタカナ・英数字・記号の全角/半角を個別に選択して一括変換。クライアントサイド処理のためデータがサーバーに送信されない
  • DevToolBox 文字コード変換: UTF-8/Shift_JIS/EUC-JP間の変換とバイト列の確認。文字化けの原因特定に便利
  • nkf (Network Kanji Filter): Linuxコマンドラインツール。バッチ処理向け
# nkf: Shift_JIS → UTF-8に一括変換(上書き)
nkf -w --overwrite legacy_data.csv

# 文字コード判定
nkf --guess unknown_file.csv
# => Shift_JIS (CRLF)

特にAPIレスポンスの確認やCSVの文字コード問題を調査する際は、オンラインツールで素早く原因を特定してからコードで修正するワークフローが効率的です。

よくある質問

Q: Excel CSVのShift_JIS問題はどう対処する?

ExcelはCSVをShift_JISで開く挙動があります(日本語Windows)。UTF-8 CSVをExcelで正しく開くにはBOM(Byte Order Mark)付きUTF-8で保存します。

// Node.js: BOM付きUTF-8で書き出し
const BOM = '\uFEFF';
fs.writeFileSync('data.csv', BOM + csvString, 'utf-8');
# Python: BOM付きUTF-8で書き出し
with open('data.csv', 'w', encoding='utf-8-sig') as f:
    f.write(csv_string)

Q: 全角半角の統一ルールはプロジェクトごとに決めるべき?

はい。一般的なルールは以下です。

文字種 推奨形式 理由
英数字 半角 正規表現・バリデーションの統一性
カタカナ 全角 可読性(半角カタカナは読みにくい)
スペース 半角 データ処理の一貫性
括弧・記号 プロジェクト依存 UIの見た目に影響

参考リンク

まとめ

日本語開発において全角/半角変換と文字コード変換は避けて通れない処理です。JavaScriptではcharCodeAtの差分計算とマッピングテーブル、PythonではNFKC正規化が基本的なアプローチです。ブラウザで手軽に確認・変換したい場合はオンラインツールが便利です。プロジェクト開始時に「英数字は半角、カタカナは全角」のルールを明文化しておくと、後々のデータクレンジングコストを大幅に削減できます。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?