В методе getview выставлять слушателя вне проверки просмотра. Попробуйте это сделать .. он работал в моем случае .. Как увеличить или уменьшить значение edittext в каждой строке списка?
Вот функция extend_file_and_insert()
, которая выполняет задание более или менее.
#include <sys/stat.h>
#include <unistd.h>
enum { BUFFERSIZE = 64 * 1024 };
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
/*
off_t is signed
ssize_t is signed
size_t is unsigned
off_t for lseek() offset and return
size_t for read()/write() length
ssize_t for read()/write() return
off_t for st_size
*/
static int extend_file_and_insert(int fd, off_t offset, char const *insert, size_t inslen)
{
char buffer[BUFFERSIZE];
struct stat sb;
int rc = -1;
if (fstat(fd, &sb) == 0)
{
if (sb.st_size > offset)
{
/* Move data after offset up by inslen bytes */
size_t bytes_to_move = sb.st_size - offset;
off_t read_end_offset = sb.st_size;
while (bytes_to_move != 0)
{
ssize_t bytes_this_time = MIN(BUFFERSIZE, bytes_to_move);
ssize_t rd_off = read_end_offset - bytes_this_time;
ssize_t wr_off = rd_off + inslen;
lseek(fd, rd_off, SEEK_SET);
if (read(fd, buffer, bytes_this_time) != bytes_this_time)
return -1;
lseek(fd, wr_off, SEEK_SET);
if (write(fd, buffer, bytes_this_time) != bytes_this_time)
return -1;
bytes_to_move -= bytes_this_time;
read_end_offset -= bytes_this_time; /* Added 2013-07-19 */
}
}
lseek(fd, offset, SEEK_SET);
write(fd, insert, inslen);
rc = 0;
}
return rc;
}
(обратите внимание на добавленную добавленную строку 2013-07-19, это была ошибка, которая показывает только когда размер буфера меньше объема данных, которые нужно скопировать в файл. Благодаря malat для указания ошибки. Код теперь проверен с помощью BUFFERSIZE = 4
.)
Это небольшой тестовый код:
#include <fcntl.h>
#include <string.h>
static const char base_data[] = "12345";
typedef struct Data
{
off_t posn;
const char *data;
} Data;
static const Data insert[] =
{
{ 2, "456" },
{ 4, "XxxxxxX" },
{ 12, "ZzzzzzzzzzzzzzzzzzzzzzzzX" },
{ 22, "YyyyyyyyyyyyyyyY" },
};
enum { NUM_INSERT = sizeof(insert) / sizeof(insert[0]) };
int main(void)
{
int fd = open("test.dat", O_RDWR | O_TRUNC | O_CREAT, 0644);
if (fd > 0)
{
ssize_t base_len = sizeof(base_data) - 1;
if (write(fd, base_data, base_len) == base_len)
{
for (int i = 0; i < NUM_INSERT; i++)
{
off_t length = strlen(insert[i].data);
if (extend_file_and_insert(fd, insert[i].posn, insert[i].data, length) != 0)
break;
lseek(fd, 0, SEEK_SET);
char buffer[BUFFERSIZE];
ssize_t nbytes;
while ((nbytes = read(fd, buffer, sizeof(buffer))) > 0)
write(1, buffer, nbytes);
write(1, "\n", 1);
}
}
close(fd);
}
return(0);
}
Он выводит результат:
12456345
1245XxxxxxX6345
1245XxxxxxX6ZzzzzzzzzzzzzzzzzzzzzzzzZ345
1245XxxxxxX6ZzzzzzzzzzYyyyyyyyyyyyyyyYzzzzzzzzzzzzzzZ345
Он должен быть протестирован на некоторых более крупных файлах (больше, чем BUFFERSIZE, но было бы разумно протестировать с BUFFERSIZE намного меньше, чем 64 KiB, я использовал 32 байта, и это казалось ОК). Я только посмотрел результаты, но шаблоны разработаны, чтобы было легко увидеть, что они верны. Код не проверяет любые вызовы lseek()
; это незначительный риск.
Я собираюсь интерпретировать ваш вопрос в широком смысле как «как я могу эффективно реализовать постоянное хранилище объекта, поддерживающего поиск по произвольному доступу по индексу и вставку с расширением». Как уже отмечалось, вы можете использовать простой линейный массив в файле, но это будет полезно только для поиска (O (1)) и довольно неэффективно для вставки (O (n)). Вы могли бы достичь O (log n) для поиска и вставки, используя вместо этого структуру данных дерева. Поддерживайте один файл, который действует как индекс, а другой, который действует как хранилище данных и представляет собой серию кусков. Каждый кусок может быть частично заполнен. Файл индекса содержит дерево (двоичное дерево или B-дерево), где каждый узел соответствует некоторому смежному фрагменту массива и содержит размер этого фрагмента (так что корневой узел содержит размер всего массива). Для двоичного дерева левый и правый дочерние узлы содержат размер левой и правой половин (приблизительно) массива. Наконец, узлы листа содержат указатель на кусок в файле хранилища данных, который содержит фактические данные. Вставка теперь включает изменение свойства 'size' узлов 'k', где 'k' - высота дерева. Когда кусок хранилища данных становится слишком полным, разделите его (выделите новый, увеличив файл или, если вы также поддерживаете удаление, возможно, из бесплатного списка пустых блоков) и перебалансируйте дерево (много стандартных способов сделать это.)
Сложно ли это звучать? Определенно! Эффективная вставка среднего файла более сложна для достижения, чем добавление.
Сначала используйте ftruncate()
, чтобы увеличить файл до конечного размера. Затем скопируйте все, начиная от старого конца и заканчивая новым, и вернитесь к точке ввода. Затем перезапишите среднее содержимое с данными, которые вы хотите вставить. Это так же эффективно, как кажется, потому что файловые системы обычно не предлагают истинную «вставку» в середине файлов.
Я согласен с остальными, но позвольте мне сформулировать решение по-другому: