---
title: 文字列と Path
url: https://doc.liz6.com/ja/rust/10-standard-library-depth/03-strings-and-path
locale: ja
area: rust
tags:
- rust
- standard-library-depth
date: 2026-06-30
modified: 2026-07-16
description: '&str は UTF-8 保証のバイトスライス参照（String はヒープ割り当て版）であり、s[0] でインデックスできません（UTF-8 では 1 文字が 1〜4 バイトのため、O(1) のインデックスは成立しません）。OsStr はプラットフォームネイティブ文字列（Unix ではバイト列、Windows では WTF-8）、Path は OsStr のパスラッパーです——クロスプラットフォームなファイル操作では、文字列連結ではなく常に Path/PathBuf を使用するのが正しい做法です。'
---

# 文字列と Path

> `&str` は UTF-8 保証のバイトスライス参照（String はヒープ割り当て版）であり、`s[0]` でインデックスできません（UTF-8 では 1 文字が 1〜4 バイトのため、O(1) のインデックスは成立しません）。`OsStr` はプラットフォームネイティブ文字列（Unix ではバイト列、Windows では WTF-8）、`Path` は `OsStr` のパスラッパーです——クロスプラットフォームなファイル操作では、文字列連結ではなく常に Path/PathBuf を使用するのが正しい做法です。

## String と &str: owned vs borrowed

```rust
let s: String = String::from("hello");  // ヒープ割り当て、可変、owned
let r: &str = "hello";                  // 静的/借用、不変
```

`String` = `Vec<u8>` + **UTF-8 妥当性保証**——コンパイラは `String` の内容が常に有効な UTF-8 であることを保証します。`into_bytes()` で内部の `Vec<u8>` を取り出すことができます（UTF-8 保証を放棄）、また `from_utf8()` でバイトから構築することもできます（`Result` を返し、無効な UTF-8 の場合は Err を返します）。

## s[0] が使えない理由

C では `s[0]` は byte を返します——ASCII には問題ありませんが、多言語では完全に正しくありません。Python では `s[0]` は最初の Unicode コードポイントを返しますが、コードポイントは必ずしも「表示可能な文字」とは限りません（é は e + ́ の 2 つのコードポイントになる可能性があります）。

Rust はこの**隠れたコストを伴うアクセス**をインデックス構文として公開しません：

```rust
let s = "こんにちは";                  // 5 文字、UTF-8 では 15 バイト
// let c = s[0];                      // コンパイルエラー: String に対するインデックスは存在しません
let c = s.chars().nth(2).unwrap();    // 'に' — O(2): 最初の 2 文字をスキップする必要があります
```

UTF-8 は可変長エンコーディングです：ASCII 文字は 1 バイト、西欧/中東の大半の文字は 2 バイト、CJK 文字は 3 バイト、絵文字は 4 バイトです。Rust で `s[n]` が O(1) になることはあり得ないため、あえて提供していません。プログラマは明示的に `.chars().nth(n)` と書く必要があり、「これにはスキャンが必要である」ことを認めることになります。

## OsStr/OsString: UTF-8 ではないシステム文字列

Unix 上のファイル名は単なる `[u8]` です——任意のバイト列であり、UTF-8 である保証はありません。Windows 上のファイル名は WTF-8 です（UTF-16 に近い）。`OsStr` はクロスプラットフォームな抽象化であり、内容に対して UTF-8 保証を行いませんが、安全に渡したり連結したりできます：

```rust
use std::ffi::OsStr;
use std::path::{Path, PathBuf};

let p = Path::new("/usr/bin");
let parent = p.parent().unwrap();    // /usr
let file = p.file_name().unwrap();   // bin
let full: PathBuf = p.join("subdir").join("file.txt");  // /usr/bin/subdir/file.txt
```

`Path` は `OsStr` のラッパーであり、パス固有のメソッド（parent, extension, components, join）が追加されています。`PathBuf` は owned 版です。重要な点は、Path は内容を String に変換することを要求しないことです——Path 上で直接操作でき、事前に UTF-8 チェックを行う必要はありません。

## 参考

- **Rust Book**: Chapter 8.2
- **Rust Reference**: OsStr, Path

*Keywords: String, &str, UTF-8, char, OsStr, Path, PathBuf, indexing, Unicode*
