Подводный камень при чтении файла с помощью File.ReadAllText

Иногда проще прочитать файл, как текстовый в однобайтовой кодировке, чтобы что-нибудь там поделать с помощью стандартных string.Replace/string.Remove и т.д., иногда даже если файл не совсем текстовый, потому что таких же удобных функций для работы с массивом байт нет (или я не нашел).
Это, наверняка, адский быдлокод, но все-таки вполне альтернатива изобретению совсем уж дикого велосипеда.

А у меня речь шла о текстовых файлах, правда, неизвестно в какой кодировке, и символах, которые нужно искать/менять. Символы от кодировки не зависели, посему любой файл можно было рассматривать, как текстовый, в любой однобайтовой кодировке. Главное, в какой кодировке открыл, в той же потом и сохранить.
Так вот File.ReadAllText пытается автоматически определить кодировку файла на основе наличия меток порядка следования байтов и принудительная установка кодировки не помогает. Если в файле встретился зловредный BOM, то ReadAllText наплюет на твои указания кодировки с высокой колокольни и откроет в той, на которую ему BOM указывает, а при сохранении, соответственно, будет глюк и текст превратится в тыкву.

Беда, конечно, решается стандартно, чтением файла с помощью StreamReader и записью с помощью StreamWriter, которые себе такой самодеятельности не позволяют, но «осадочек остался».

Пример
Скачать

Мухосранск. Говно. Тоскливо.

Мухосранск. Говно. Тоскливо.
Дети. Дом. Работа. Пиво.
Геморрой. Камаз. Гараж.
Десять лет водилой стаж.
Раз в пять лет с женой в кино.
Мухосранск. Тоска. Говно.
Водка. Патриот. Россия.
Шарфик красно-бело-синий.
Ящик. Киселёв на Первом.
Украина. Киев. Нервы.
Танцы. Шум. «Крымнаш». Веселье.
Утро. Санкции. Похмелье.
Цены. Доллар. Банк. Кредит.
Тёща как всегда нудит.
Снова Киселёв на Первом.
Водка. Вещмешок. Консервы.
Секс с женой как в первый раз.
Поезд. В путь. Спасать Донбасс.
Форма. Каска. Полигон.
Гумконвоем в Краснодон.
ЛНР. Блокпост. Укропы.
Первый бой. Три пули в жопе.
Страх. Обстрел. Осколок «Града».
Труп. Мешок. Рефрижератор.
Крест. Венок. Вдова. Плаксиво.
Мухосранск. Говно. Тоскливо.

Оператор наведения Дон Олесь

XuliOrganizzer. Простенький самописный органайзер на C#

Нет, оно не читается, как хули, органайзер. Но, может быть, что и подразумевается. 🙂
Это маленькая программа-органайзер для XP, 7, 8 и Vista. На 10 никто из нас ее запускать не пробовал, из за отсутствия таковой.

Что умеет:
— Собственно, напоминания по расписанию о событиях. Ну там кота покормить, или не забыть выключить самогонный аппарат, или продать славянский шкаф.

Возможны напоминания как в виде всплывающих подсказок в трее, так и в отдельном окне, повтор напоминаний через заданное время, звуковое оповещение.
Имеется возможность активировать/деактивировать задание-напоминание, есть контроль просроченных заданий и возможность немедленного выполнения таковых при старте программы.

— Запуск программ по расписанию, как с уведомлением, так и без.

— Симпатичный таймер обратного отсчета

— Текстовые заметки

Для заметок есть «корзина», т.е. случайно удаленную заметку можно восстановить.

Все данные хранятся в XML, в настройках можно посмотреть путь к файлу.

Писал в основном Леша, изредка виртуально пиная всех вокруг, и в основном для меня, потому что я давно хотел удовлетворяющий меня органайзер с напоминаниями, а в сети не было такого, который бы меня устраивал.

Распространяется свободно, как обычно, по лицензии Хекса.

Еще скриншоты

Скачать
Зеркало

Исходники:

Скачать
На Github

C#. Windows Forms. Режим замены текста по нажатию клавиши Insert в TextBox.

То есть, задача сделать, чтоб было как в нормальном текстовом редакторе, нажимаем Ins, и символы перед курсором заменяются на введенные с клавиатуры. Нажимаем еще раз и символы вставляются как обычно.
Элемент управления TextBox почему-то из коробки это не поддерживает, поддерживает MaskedTextBox, но и стандартный TextBox вполне можно допилить. Не знаю, почему на первых строках в поисковике какой-то ужас со StringBuilder‘ами и чуть ли не вызовом WINAPI, хотя все гораздо проще.

Заводим в форме логическую переменную, которая будет отвечать за то, какой режим ввода сейчас true — замена, false — обычная вставка.

bool InsertMode = false;

В обработчик события KeyUp помещаем код, который будет менять флаг, если был нажата клавиша Insert:

private void txtTest_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Insert)
            {
                InsertMode = !InsertMode;
            }

        }

В обработчике KeyPress код следующий

private void txtTest_KeyPress(object sender, KeyPressEventArgs e)
        {
            //Вытаскиваю объект, который вызвал событие, 
            //чтоб можно было подключить несколько TextBox'ов
            TextBox tb = (TextBox)sender;
            
            //если включен соотв. режим, курсор не в конце текста
            //и не нажата какая-либо управляющая клавиша
            //заменим символ перед курсором
            if (InsertMode && tb.SelectionStart < tb.TextLength 
                && !Char.IsControl(e.KeyChar))
            {                                
                //выделяем 1 символ перед курсором
                //область выделения автоматически заменится 
                //символом, введенным  с клавиатуры
                tb.SelectionLength  = 1;

                //если выделен символ перевода строки, значит это конец строки 
                //в multiline TextBox,  
                if (tb.SelectedText == "\r" || tb.SelectedText == "\n")
                    tb.SelectionLength = 0; //не надо ничего
                                           //заменять, убираем выделение
            }
        }

Вот. Комментарев больше кода 🙂

Можно сделать замену текста по кругу, т.е., когда дошли до последнего возможного символа, начинаем заменять с первого. Может пригодиться, если строка какая-то небольшая, например две цифры секунд, какой-нибудь код, почтовый индекс и т.д.

Надо всего лишь модифицировать первое условие, чтоб исключить проверку на длину строки и добавить проверку на TextBox.MaxLength

if (InsertMode && !Char.IsControl(e.KeyChar))
{
	//замена по кругу
            if (tb.SelectionStart == tb.MaxLength) tb.SelectionStart = 0;
            //   [...]
}

Достигли последнего возможного символа, перескочили в начало текстового поля.

Пример 1 Пример 2
Скачать проекты